drm/nouveau/clk: rename from clock (no binary change)
authorBen Skeggs <bskeggs@redhat.com>
Tue, 13 Jan 2015 13:37:38 +0000 (23:37 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 22 Jan 2015 02:17:42 +0000 (12:17 +1000)
Rename to match the Linux subsystem responsible for the same kind of
things.  Will be investigating how feasible it will be to expose the
GPU clock trees with it at some point.

The namespace of NVKM is being changed to nvkm_ instead of nouveau_,
which will be used for the DRM part of the driver.  This is being
done in order to make it very clear as to what part of the driver a
given symbol belongs to, and as a minor step towards splitting the
DRM driver out to be able to stand on its own (for virt).

Because there's already a large amount of churn here anyway, this is
as good a time as any to also switch to NVIDIA's device and chipset
naming to ease collaboration with them.

A comparison of objdump disassemblies proves no code changes.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
60 files changed:
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/hw.c
drivers/gpu/drm/nouveau/include/nvif/device.h
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvkm/subdev/clock.h [deleted file]
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c
drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nv04.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nv10.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nv20.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nv30.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nvc0.c
drivers/gpu/drm/nouveau/nvkm/engine/device/nve0.c
drivers/gpu/drm/nouveau/nvkm/engine/perfmon/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv84.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nva3.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nva3.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nvaa.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nvc0.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/nve0.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnva3.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/Kbuild [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/base.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/gk20a.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv04.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv40.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv50.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv50.h [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv84.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nva3.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nva3.h [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nvaa.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nvc0.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/nve0.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/pll.h [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/pllnv04.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/pllnva3.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/clock/seq.h [deleted file]
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnva3.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnvc0.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnve0.c
drivers/gpu/drm/nouveau/nvkm/subdev/pwr/gk20a.c

index 38402ade68351f9ecab27eed823c0a6d131a75b5..f8ddae26dfbf5b1aff5b3f98f34e6e7007ed830d 100644 (file)
@@ -41,7 +41,7 @@
 #include "disp.h"
 
 #include <subdev/bios/pll.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 
 static int
 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
@@ -113,7 +113,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
        struct drm_device *dev = crtc->dev;
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_bios *bios = nvkm_bios(&drm->device);
-       struct nouveau_clock *clk = nvkm_clock(&drm->device);
+       struct nouveau_clk *clk = nvkm_clk(&drm->device);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
        struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index];
index 3d4c1930076882c5280ee81f573ea11e624a95f7..f9491f926c14e3c2f48f4bfca72721a09e3929da 100644 (file)
@@ -253,7 +253,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head)
 
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nvif_device *device = &drm->device;
-       struct nouveau_clock *clk = nvkm_clock(device);
+       struct nouveau_clk *clk = nvkm_clk(device);
        struct nouveau_bios *bios = nvkm_bios(device);
        struct nvbios_pll pll_lim;
        struct nouveau_pll_vals pv;
@@ -463,7 +463,7 @@ nv_load_state_ramdac(struct drm_device *dev, int head,
                     struct nv04_mode_state *state)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
-       struct nouveau_clock *clk = nvkm_clock(&drm->device);
+       struct nouveau_clk *clk = nvkm_clk(&drm->device);
        struct nv04_crtc_reg *regp = &state->crtc_reg[head];
        uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
        int i;
index 4aa1b93a8cd4f0ef24f71ec1c9f08ecf92da6bff..e73a16dd97fa93e1794b3393c748f2c0149c329e 100644 (file)
@@ -32,7 +32,7 @@ void nvif_device_ref(struct nvif_device *, struct nvif_device **);
 #include <subdev/vm.h>
 #include <subdev/bar.h>
 #include <subdev/gpio.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/i2c.h>
 #include <subdev/timer.h>
 #include <subdev/therm.h>
@@ -43,7 +43,7 @@ void nvif_device_ref(struct nvif_device *, struct nvif_device **);
 #define nvkm_vmmgr(a) nouveau_vmmgr(nvkm_device(a))
 #define nvkm_bar(a) nouveau_bar(nvkm_device(a))
 #define nvkm_gpio(a) nouveau_gpio(nvkm_device(a))
-#define nvkm_clock(a) nouveau_clock(nvkm_device(a))
+#define nvkm_clk(a) nouveau_clk(nvkm_device(a))
 #define nvkm_i2c(a) nouveau_i2c(nvkm_device(a))
 #define nvkm_timer(a) nouveau_timer(nvkm_device(a))
 #define nvkm_wait(a,b,c,d) nv_wait(nvkm_timer(a), (b), (c), (d))
index 21a055aca5131c9d46e402a3a9fddbdd19ad2dc8..87ecf6d23d9e5e69039201aa26191bde43daf7dc 100644 (file)
@@ -38,7 +38,7 @@ enum nv_subdev_type {
        NVDEV_SUBDEV_PWR,
        NVDEV_SUBDEV_VOLT,
        NVDEV_SUBDEV_THERM,
-       NVDEV_SUBDEV_CLOCK,
+       NVDEV_SUBDEV_CLK,
 
        NVDEV_ENGINE_FIRST,
        NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
new file mode 100644 (file)
index 0000000..4524d4e
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef __NOUVEAU_CLK_H__
+#define __NOUVEAU_CLK_H__
+
+#include <core/device.h>
+#include <core/subdev.h>
+
+struct nouveau_pll_vals;
+struct nvbios_pll;
+
+enum nv_clk_src {
+       nv_clk_src_crystal,
+       nv_clk_src_href,
+
+       nv_clk_src_hclk,
+       nv_clk_src_hclkm3,
+       nv_clk_src_hclkm3d2,
+       nv_clk_src_hclkm2d3, /* NVAA */
+       nv_clk_src_hclkm4, /* NVAA */
+       nv_clk_src_cclk, /* NVAA */
+
+       nv_clk_src_host,
+
+       nv_clk_src_sppll0,
+       nv_clk_src_sppll1,
+
+       nv_clk_src_mpllsrcref,
+       nv_clk_src_mpllsrc,
+       nv_clk_src_mpll,
+       nv_clk_src_mdiv,
+
+       nv_clk_src_core,
+       nv_clk_src_core_intm,
+       nv_clk_src_shader,
+
+       nv_clk_src_mem,
+
+       nv_clk_src_gpc,
+       nv_clk_src_rop,
+       nv_clk_src_hubk01,
+       nv_clk_src_hubk06,
+       nv_clk_src_hubk07,
+       nv_clk_src_copy,
+       nv_clk_src_daemon,
+       nv_clk_src_disp,
+       nv_clk_src_vdec,
+
+       nv_clk_src_dom6,
+
+       nv_clk_src_max,
+};
+
+struct nouveau_cstate {
+       struct list_head head;
+       u8  voltage;
+       u32 domain[nv_clk_src_max];
+};
+
+struct nouveau_pstate {
+       struct list_head head;
+       struct list_head list; /* c-states */
+       struct nouveau_cstate base;
+       u8 pstate;
+       u8 fanspeed;
+};
+
+struct nouveau_clk {
+       struct nouveau_subdev base;
+
+       struct nouveau_domain *domains;
+       struct nouveau_pstate bstate;
+
+       struct list_head states;
+       int state_nr;
+
+       struct work_struct work;
+       wait_queue_head_t wait;
+       atomic_t waiting;
+
+       struct nvkm_notify pwrsrc_ntfy;
+       int pwrsrc;
+       int pstate; /* current */
+       int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
+       int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
+       int astate; /* perfmon adjustment (base) */
+       int tstate; /* thermal adjustment (max-) */
+       int dstate; /* display adjustment (min+) */
+
+       bool allow_reclock;
+
+       int  (*read)(struct nouveau_clk *, enum nv_clk_src);
+       int  (*calc)(struct nouveau_clk *, struct nouveau_cstate *);
+       int  (*prog)(struct nouveau_clk *);
+       void (*tidy)(struct nouveau_clk *);
+
+       /*XXX: die, these are here *only* to support the completely
+        *     bat-shit insane what-was-nouveau_hw.c code
+        */
+       int (*pll_calc)(struct nouveau_clk *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *pv);
+       int (*pll_prog)(struct nouveau_clk *, u32 reg1,
+                       struct nouveau_pll_vals *pv);
+};
+
+static inline struct nouveau_clk *
+nouveau_clk(void *obj)
+{
+       return (void *)nouveau_subdev(obj, NVDEV_SUBDEV_CLK);
+}
+
+struct nouveau_domain {
+       enum nv_clk_src name;
+       u8 bios; /* 0xff for none */
+#define NVKM_CLK_DOM_FLAG_CORE 0x01
+       u8 flags;
+       const char *mname;
+       int mdiv;
+};
+
+#define nouveau_clk_create(p,e,o,i,r,s,n,d)                                  \
+       nouveau_clk_create_((p), (e), (o), (i), (r), (s), (n), sizeof(**d),  \
+                             (void **)d)
+#define nouveau_clk_destroy(p) ({                                            \
+       struct nouveau_clk *clk = (p);                                       \
+       _nouveau_clk_dtor(nv_object(clk));                                   \
+})
+#define nouveau_clk_init(p) ({                                               \
+       struct nouveau_clk *clk = (p);                                       \
+       _nouveau_clk_init(nv_object(clk));                                   \
+})
+#define nouveau_clk_fini(p,s) ({                                             \
+       struct nouveau_clk *clk = (p);                                       \
+       _nouveau_clk_fini(nv_object(clk), (s));                              \
+})
+
+int  nouveau_clk_create_(struct nouveau_object *, struct nouveau_object *,
+                          struct nouveau_oclass *,
+                          struct nouveau_domain *, struct nouveau_pstate *,
+                          int, bool, int, void **);
+void _nouveau_clk_dtor(struct nouveau_object *);
+int  _nouveau_clk_init(struct nouveau_object *);
+int  _nouveau_clk_fini(struct nouveau_object *, bool);
+
+extern struct nouveau_oclass nv04_clk_oclass;
+extern struct nouveau_oclass nv40_clk_oclass;
+extern struct nouveau_oclass *nv50_clk_oclass;
+extern struct nouveau_oclass *nv84_clk_oclass;
+extern struct nouveau_oclass *nvaa_clk_oclass;
+extern struct nouveau_oclass nva3_clk_oclass;
+extern struct nouveau_oclass nvc0_clk_oclass;
+extern struct nouveau_oclass nve0_clk_oclass;
+extern struct nouveau_oclass gk20a_clk_oclass;
+
+int nv04_clk_pll_set(struct nouveau_clk *, u32 type, u32 freq);
+int nv04_clk_pll_calc(struct nouveau_clk *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *);
+int nv04_clk_pll_prog(struct nouveau_clk *, u32 reg1,
+                       struct nouveau_pll_vals *);
+int nva3_clk_pll_calc(struct nouveau_clk *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *);
+
+int nouveau_clk_ustate(struct nouveau_clk *, int req, int pwr);
+int nouveau_clk_astate(struct nouveau_clk *, int req, int rel, bool wait);
+int nouveau_clk_dstate(struct nouveau_clk *, int req, int rel);
+int nouveau_clk_tstate(struct nouveau_clk *, int req, int rel);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clock.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clock.h
deleted file mode 100644 (file)
index 39ad2d2..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef __NOUVEAU_CLOCK_H__
-#define __NOUVEAU_CLOCK_H__
-
-#include <core/device.h>
-#include <core/subdev.h>
-
-struct nouveau_pll_vals;
-struct nvbios_pll;
-
-enum nv_clk_src {
-       nv_clk_src_crystal,
-       nv_clk_src_href,
-
-       nv_clk_src_hclk,
-       nv_clk_src_hclkm3,
-       nv_clk_src_hclkm3d2,
-       nv_clk_src_hclkm2d3, /* NVAA */
-       nv_clk_src_hclkm4, /* NVAA */
-       nv_clk_src_cclk, /* NVAA */
-
-       nv_clk_src_host,
-
-       nv_clk_src_sppll0,
-       nv_clk_src_sppll1,
-
-       nv_clk_src_mpllsrcref,
-       nv_clk_src_mpllsrc,
-       nv_clk_src_mpll,
-       nv_clk_src_mdiv,
-
-       nv_clk_src_core,
-       nv_clk_src_core_intm,
-       nv_clk_src_shader,
-
-       nv_clk_src_mem,
-
-       nv_clk_src_gpc,
-       nv_clk_src_rop,
-       nv_clk_src_hubk01,
-       nv_clk_src_hubk06,
-       nv_clk_src_hubk07,
-       nv_clk_src_copy,
-       nv_clk_src_daemon,
-       nv_clk_src_disp,
-       nv_clk_src_vdec,
-
-       nv_clk_src_dom6,
-
-       nv_clk_src_max,
-};
-
-struct nouveau_cstate {
-       struct list_head head;
-       u8  voltage;
-       u32 domain[nv_clk_src_max];
-};
-
-struct nouveau_pstate {
-       struct list_head head;
-       struct list_head list; /* c-states */
-       struct nouveau_cstate base;
-       u8 pstate;
-       u8 fanspeed;
-};
-
-struct nouveau_clock {
-       struct nouveau_subdev base;
-
-       struct nouveau_clocks *domains;
-       struct nouveau_pstate bstate;
-
-       struct list_head states;
-       int state_nr;
-
-       struct work_struct work;
-       wait_queue_head_t wait;
-       atomic_t waiting;
-
-       struct nvkm_notify pwrsrc_ntfy;
-       int pwrsrc;
-       int pstate; /* current */
-       int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
-       int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
-       int astate; /* perfmon adjustment (base) */
-       int tstate; /* thermal adjustment (max-) */
-       int dstate; /* display adjustment (min+) */
-
-       bool allow_reclock;
-
-       int  (*read)(struct nouveau_clock *, enum nv_clk_src);
-       int  (*calc)(struct nouveau_clock *, struct nouveau_cstate *);
-       int  (*prog)(struct nouveau_clock *);
-       void (*tidy)(struct nouveau_clock *);
-
-       /*XXX: die, these are here *only* to support the completely
-        *     bat-shit insane what-was-nouveau_hw.c code
-        */
-       int (*pll_calc)(struct nouveau_clock *, struct nvbios_pll *,
-                       int clk, struct nouveau_pll_vals *pv);
-       int (*pll_prog)(struct nouveau_clock *, u32 reg1,
-                       struct nouveau_pll_vals *pv);
-};
-
-static inline struct nouveau_clock *
-nouveau_clock(void *obj)
-{
-       return (void *)nouveau_subdev(obj, NVDEV_SUBDEV_CLOCK);
-}
-
-struct nouveau_clocks {
-       enum nv_clk_src name;
-       u8 bios; /* 0xff for none */
-#define NVKM_CLK_DOM_FLAG_CORE 0x01
-       u8 flags;
-       const char *mname;
-       int mdiv;
-};
-
-#define nouveau_clock_create(p,e,o,i,r,s,n,d)                                  \
-       nouveau_clock_create_((p), (e), (o), (i), (r), (s), (n), sizeof(**d),  \
-                             (void **)d)
-#define nouveau_clock_destroy(p) ({                                            \
-       struct nouveau_clock *clk = (p);                                       \
-       _nouveau_clock_dtor(nv_object(clk));                                   \
-})
-#define nouveau_clock_init(p) ({                                               \
-       struct nouveau_clock *clk = (p);                                       \
-       _nouveau_clock_init(nv_object(clk));                                   \
-})
-#define nouveau_clock_fini(p,s) ({                                             \
-       struct nouveau_clock *clk = (p);                                       \
-       _nouveau_clock_fini(nv_object(clk), (s));                              \
-})
-
-int  nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
-                          struct nouveau_oclass *,
-                          struct nouveau_clocks *, struct nouveau_pstate *,
-                          int, bool, int, void **);
-void _nouveau_clock_dtor(struct nouveau_object *);
-int  _nouveau_clock_init(struct nouveau_object *);
-int  _nouveau_clock_fini(struct nouveau_object *, bool);
-
-extern struct nouveau_oclass nv04_clock_oclass;
-extern struct nouveau_oclass nv40_clock_oclass;
-extern struct nouveau_oclass *nv50_clock_oclass;
-extern struct nouveau_oclass *nv84_clock_oclass;
-extern struct nouveau_oclass *nvaa_clock_oclass;
-extern struct nouveau_oclass nva3_clock_oclass;
-extern struct nouveau_oclass nvc0_clock_oclass;
-extern struct nouveau_oclass nve0_clock_oclass;
-extern struct nouveau_oclass gk20a_clock_oclass;
-
-int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq);
-int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
-                       int clk, struct nouveau_pll_vals *);
-int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
-                       struct nouveau_pll_vals *);
-int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
-                       int clk, struct nouveau_pll_vals *);
-
-int nouveau_clock_ustate(struct nouveau_clock *, int req, int pwr);
-int nouveau_clock_astate(struct nouveau_clock *, int req, int rel, bool wait);
-int nouveau_clock_dstate(struct nouveau_clock *, int req, int rel);
-int nouveau_clock_tstate(struct nouveau_clock *, int req, int rel);
-
-#endif
index f74f9cbbf3d862efb8f802941dff22d49907287c..f9589e8935d9e1a8536d85740c4256a70b20d374 100644 (file)
@@ -209,7 +209,7 @@ static const u64 disable_map[] = {
        [NVDEV_SUBDEV_DEVINIT]  = NV_DEVICE_V0_DISABLE_CORE,
        [NVDEV_SUBDEV_GPIO]     = NV_DEVICE_V0_DISABLE_CORE,
        [NVDEV_SUBDEV_I2C]      = NV_DEVICE_V0_DISABLE_CORE,
-       [NVDEV_SUBDEV_CLOCK]    = NV_DEVICE_V0_DISABLE_CORE,
+       [NVDEV_SUBDEV_CLK  ]    = NV_DEVICE_V0_DISABLE_CORE,
        [NVDEV_SUBDEV_MXM]      = NV_DEVICE_V0_DISABLE_CORE,
        [NVDEV_SUBDEV_MC]       = NV_DEVICE_V0_DISABLE_CORE,
        [NVDEV_SUBDEV_BUS]      = NV_DEVICE_V0_DISABLE_CORE,
index e34101a3490ee3210c2382cba07a9393b924d843..7a7632e65c772a138f22e4e51818cbeb54b7f73c 100644 (file)
@@ -28,7 +28,7 @@
 #include <nvif/class.h>
 #include <nvif/ioctl.h>
 
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 
 #include "priv.h"
 
@@ -39,7 +39,7 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object,
        union {
                struct nvif_control_pstate_info_v0 v0;
        } *args = data;
-       struct nouveau_clock *clk = nouveau_clock(object);
+       struct nouveau_clk *clk = nouveau_clk(object);
        int ret;
 
        nv_ioctl(object, "control pstate info size %d\n", size);
@@ -73,8 +73,8 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object,
        union {
                struct nvif_control_pstate_attr_v0 v0;
        } *args = data;
-       struct nouveau_clock *clk = nouveau_clock(object);
-       struct nouveau_clocks *domain;
+       struct nouveau_clk *clk = nouveau_clk(object);
+       struct nouveau_domain *domain;
        struct nouveau_pstate *pstate;
        struct nouveau_cstate *cstate;
        int i = 0, j = -1;
@@ -147,7 +147,7 @@ nouveau_control_mthd_pstate_user(struct nouveau_object *object,
        union {
                struct nvif_control_pstate_user_v0 v0;
        } *args = data;
-       struct nouveau_clock *clk = nouveau_clock(object);
+       struct nouveau_clk *clk = nouveau_clk(object);
        int ret;
 
        nv_ioctl(object, "control pstate user size %d\n", size);
@@ -161,10 +161,10 @@ nouveau_control_mthd_pstate_user(struct nouveau_object *object,
                return ret;
 
        if (args->v0.pwrsrc >= 0) {
-               ret |= nouveau_clock_ustate(clk, args->v0.ustate, args->v0.pwrsrc);
+               ret |= nouveau_clk_ustate(clk, args->v0.ustate, args->v0.pwrsrc);
        } else {
-               ret |= nouveau_clock_ustate(clk, args->v0.ustate, 0);
-               ret |= nouveau_clock_ustate(clk, args->v0.ustate, 1);
+               ret |= nouveau_clk_ustate(clk, args->v0.ustate, 0);
+               ret |= nouveau_clk_ustate(clk, args->v0.ustate, 1);
        }
 
        return ret;
index 4e74a3376de88d9a695eed859fd17ad136a28c91..e453a52135d7bfccd79eae845ee60b00a5786d41 100644 (file)
@@ -27,7 +27,7 @@
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
 #include <subdev/fuse.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/therm.h>
 #include <subdev/mxm.h>
 #include <subdev/devinit.h>
@@ -64,7 +64,7 @@ gm100_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gm107_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gm107_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm107_devinit_oclass;
@@ -106,7 +106,7 @@ gm100_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gm107_fuse_oclass;
 #if 0
                /* looks to be some non-trivial changes */
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                /* priv ring says no to 0x10eb14 writes */
                device->oclass[NVDEV_SUBDEV_THERM  ] = &gm107_therm_oclass;
 #endif
index 573b55f5c2f94597e101d65ab8ee3c150fd3656b..dff51984ea941656d53e564a23ebdeb6cf555460 100644 (file)
@@ -25,7 +25,7 @@
 #include <subdev/bios.h>
 #include <subdev/bus.h>
 #include <subdev/i2c.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/devinit.h>
 #include <subdev/mc.h>
 #include <subdev/timer.h>
@@ -48,7 +48,7 @@ nv04_identify(struct nouveau_device *device)
                device->cname = "NV04";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv04_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -66,7 +66,7 @@ nv04_identify(struct nouveau_device *device)
                device->cname = "NV05";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv05_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
index 183a85a6204e33b20d8c83d11653751bb67adcd0..af63f5b95f01dcdef770e9397b6dee63693b36eb 100644 (file)
@@ -26,7 +26,7 @@
 #include <subdev/bus.h>
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/devinit.h>
 #include <subdev/mc.h>
 #include <subdev/timer.h>
@@ -50,7 +50,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -67,7 +67,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -86,7 +86,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -105,7 +105,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -124,7 +124,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -143,7 +143,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -162,7 +162,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -181,7 +181,7 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
index aa564c68a920b50fe7a4efaabc20ac498b5b3880..eddeb126c7ec9cc63d2eb1041bc951cc73fc37da 100644 (file)
@@ -26,7 +26,7 @@
 #include <subdev/bus.h>
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/therm.h>
 #include <subdev/devinit.h>
 #include <subdev/mc.h>
@@ -51,7 +51,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -70,7 +70,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -89,7 +89,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -108,7 +108,7 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
index 11bd31da82ab1d1fc0da76b8f00153e80611a331..6fe2d130a2cea9cc22c1d35e88c647a7605acd63 100644 (file)
@@ -26,7 +26,7 @@
 #include <subdev/bus.h>
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/devinit.h>
 #include <subdev/mc.h>
 #include <subdev/timer.h>
@@ -51,7 +51,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -70,7 +70,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
@@ -89,7 +89,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
@@ -109,7 +109,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
@@ -129,7 +129,7 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv04_clk_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
index e96c223cb797de20671838d54abdcdd224afd0d9..d85edd87cec8c00431ca0b81553ff08648dfeff8 100644 (file)
@@ -27,7 +27,7 @@
 #include <subdev/vm.h>
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/therm.h>
 #include <subdev/devinit.h>
 #include <subdev/mc.h>
@@ -55,7 +55,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -78,7 +78,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -101,7 +101,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -124,7 +124,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -147,7 +147,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -170,7 +170,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -193,7 +193,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -216,7 +216,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
@@ -239,7 +239,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
@@ -262,7 +262,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
@@ -285,7 +285,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
@@ -308,7 +308,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
@@ -331,7 +331,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv4e_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
@@ -354,7 +354,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
@@ -377,7 +377,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
@@ -400,7 +400,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nv40_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
index 96f568d1321bc8d44abca71d98956a8dc3b01799..ccf82ab168811a3a0055ed150287218c5eee196d 100644 (file)
@@ -27,7 +27,7 @@
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
 #include <subdev/fuse.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/therm.h>
 #include <subdev/mxm.h>
 #include <subdev/devinit.h>
@@ -64,7 +64,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv50_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv50_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
@@ -90,7 +90,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
@@ -119,7 +119,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
@@ -148,7 +148,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
@@ -177,7 +177,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
@@ -206,7 +206,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
@@ -235,7 +235,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
@@ -264,7 +264,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nv84_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
@@ -293,7 +293,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nvaa_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
@@ -322,7 +322,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] =  nvaa_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
@@ -351,7 +351,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nva3_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
@@ -382,7 +382,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nva3_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
@@ -412,7 +412,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nva3_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
@@ -442,7 +442,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] =  &g80_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nva3_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass;
index 72a40f95d048e06c9bc625ed2e0575edbce6e933..ff5b2ab674bd4a8f931604e1d707026b6a6d750b 100644 (file)
@@ -27,7 +27,7 @@
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
 #include <subdev/fuse.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/therm.h>
 #include <subdev/mxm.h>
 #include <subdev/devinit.h>
@@ -64,7 +64,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -97,7 +97,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -130,7 +130,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -162,7 +162,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -195,7 +195,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -227,7 +227,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -259,7 +259,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv94_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -292,7 +292,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nvd0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -324,7 +324,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nvd0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  gf117_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nvc0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
index d308aee028f0c9419eeb4b6e5fcda14b86ead824..7c02ff5b13edfb12413a9d3ace577e47c7d47433 100644 (file)
@@ -27,7 +27,7 @@
 #include <subdev/gpio.h>
 #include <subdev/i2c.h>
 #include <subdev/fuse.h>
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/therm.h>
 #include <subdev/mxm.h>
 #include <subdev/devinit.h>
@@ -64,7 +64,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -98,7 +98,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -132,7 +132,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -162,7 +162,7 @@ nve0_identify(struct nouveau_device *device)
                break;
        case 0xea:
                device->cname = "GK20A";
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &gk20a_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &gk20a_clk_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  gk20a_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
@@ -188,7 +188,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -222,7 +222,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nvd0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -256,7 +256,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
@@ -289,7 +289,7 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_FUSE   ] = &gf100_fuse_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLK    ] = &nve0_clk_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
index 63013812f7c952d7e6648a9ccebea08dc71b5605..3a9359e291792330ccbd68f3a400e4fb22d26d88 100644 (file)
@@ -28,7 +28,7 @@
 #include <nvif/class.h>
 #include <nvif/ioctl.h>
 
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 
 #include "priv.h"
 
index 10ef07cf3f91353a41cf850816e56cfb44c5669e..39f800a6f1e4b3dd7eaabfb7ca748341ade176ea 100644 (file)
@@ -1,7 +1,7 @@
 include $(src)/nvkm/subdev/bar/Kbuild
 include $(src)/nvkm/subdev/bios/Kbuild
 include $(src)/nvkm/subdev/bus/Kbuild
-include $(src)/nvkm/subdev/clock/Kbuild
+include $(src)/nvkm/subdev/clk/Kbuild
 include $(src)/nvkm/subdev/devinit/Kbuild
 include $(src)/nvkm/subdev/fb/Kbuild
 include $(src)/nvkm/subdev/fuse/Kbuild
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild
new file mode 100644 (file)
index 0000000..94d10a9
--- /dev/null
@@ -0,0 +1,12 @@
+nvkm-y += nvkm/subdev/clk/base.o
+nvkm-y += nvkm/subdev/clk/nv04.o
+nvkm-y += nvkm/subdev/clk/nv40.o
+nvkm-y += nvkm/subdev/clk/nv50.o
+nvkm-y += nvkm/subdev/clk/nv84.o
+nvkm-y += nvkm/subdev/clk/nva3.o
+nvkm-y += nvkm/subdev/clk/nvaa.o
+nvkm-y += nvkm/subdev/clk/nvc0.o
+nvkm-y += nvkm/subdev/clk/nve0.o
+nvkm-y += nvkm/subdev/clk/gk20a.o
+nvkm-y += nvkm/subdev/clk/pllnv04.o
+nvkm-y += nvkm/subdev/clk/pllnva3.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
new file mode 100644 (file)
index 0000000..a0c21ec
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <core/option.h>
+
+#include <subdev/clk.h>
+#include <subdev/therm.h>
+#include <subdev/volt.h>
+#include <subdev/fb.h>
+
+#include <subdev/bios.h>
+#include <subdev/bios/boost.h>
+#include <subdev/bios/cstep.h>
+#include <subdev/bios/perf.h>
+
+/******************************************************************************
+ * misc
+ *****************************************************************************/
+static u32
+nouveau_clk_adjust(struct nouveau_clk *clk, bool adjust,
+                    u8 pstate, u8 domain, u32 input)
+{
+       struct nouveau_bios *bios = nouveau_bios(clk);
+       struct nvbios_boostE boostE;
+       u8  ver, hdr, cnt, len;
+       u16 data;
+
+       data = nvbios_boostEm(bios, pstate, &ver, &hdr, &cnt, &len, &boostE);
+       if (data) {
+               struct nvbios_boostS boostS;
+               u8  idx = 0, sver, shdr;
+               u16 subd;
+
+               input = max(boostE.min, input);
+               input = min(boostE.max, input);
+               do {
+                       sver = ver;
+                       shdr = hdr;
+                       subd = nvbios_boostSp(bios, idx++, data, &sver, &shdr,
+                                             cnt, len, &boostS);
+                       if (subd && boostS.domain == domain) {
+                               if (adjust)
+                                       input = input * boostS.percent / 100;
+                               input = max(boostS.min, input);
+                               input = min(boostS.max, input);
+                               break;
+                       }
+               } while (subd);
+       }
+
+       return input;
+}
+
+/******************************************************************************
+ * C-States
+ *****************************************************************************/
+static int
+nouveau_cstate_prog(struct nouveau_clk *clk,
+                   struct nouveau_pstate *pstate, int cstatei)
+{
+       struct nouveau_therm *ptherm = nouveau_therm(clk);
+       struct nouveau_volt *volt = nouveau_volt(clk);
+       struct nouveau_cstate *cstate;
+       int ret;
+
+       if (!list_empty(&pstate->list)) {
+               cstate = list_entry(pstate->list.prev, typeof(*cstate), head);
+       } else {
+               cstate = &pstate->base;
+       }
+
+       if (ptherm) {
+               ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1);
+               if (ret && ret != -ENODEV) {
+                       nv_error(clk, "failed to raise fan speed: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (volt) {
+               ret = volt->set_id(volt, cstate->voltage, +1);
+               if (ret && ret != -ENODEV) {
+                       nv_error(clk, "failed to raise voltage: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = clk->calc(clk, cstate);
+       if (ret == 0) {
+               ret = clk->prog(clk);
+               clk->tidy(clk);
+       }
+
+       if (volt) {
+               ret = volt->set_id(volt, cstate->voltage, -1);
+               if (ret && ret != -ENODEV)
+                       nv_error(clk, "failed to lower voltage: %d\n", ret);
+       }
+
+       if (ptherm) {
+               ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1);
+               if (ret && ret != -ENODEV)
+                       nv_error(clk, "failed to lower fan speed: %d\n", ret);
+       }
+
+       return 0;
+}
+
+static void
+nouveau_cstate_del(struct nouveau_cstate *cstate)
+{
+       list_del(&cstate->head);
+       kfree(cstate);
+}
+
+static int
+nouveau_cstate_new(struct nouveau_clk *clk, int idx,
+                  struct nouveau_pstate *pstate)
+{
+       struct nouveau_bios *bios = nouveau_bios(clk);
+       struct nouveau_domain *domain = clk->domains;
+       struct nouveau_cstate *cstate = NULL;
+       struct nvbios_cstepX cstepX;
+       u8  ver, hdr;
+       u16 data;
+
+       data = nvbios_cstepXp(bios, idx, &ver, &hdr, &cstepX);
+       if (!data)
+               return -ENOENT;
+
+       cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
+       if (!cstate)
+               return -ENOMEM;
+
+       *cstate = pstate->base;
+       cstate->voltage = cstepX.voltage;
+
+       while (domain && domain->name != nv_clk_src_max) {
+               if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
+                       u32 freq = nouveau_clk_adjust(clk, true,
+                                                       pstate->pstate,
+                                                       domain->bios,
+                                                       cstepX.freq);
+                       cstate->domain[domain->name] = freq;
+               }
+               domain++;
+       }
+
+       list_add(&cstate->head, &pstate->list);
+       return 0;
+}
+
+/******************************************************************************
+ * P-States
+ *****************************************************************************/
+static int
+nouveau_pstate_prog(struct nouveau_clk *clk, int pstatei)
+{
+       struct nouveau_fb *pfb = nouveau_fb(clk);
+       struct nouveau_pstate *pstate;
+       int ret, idx = 0;
+
+       list_for_each_entry(pstate, &clk->states, head) {
+               if (idx++ == pstatei)
+                       break;
+       }
+
+       nv_debug(clk, "setting performance state %d\n", pstatei);
+       clk->pstate = pstatei;
+
+       if (pfb->ram->calc) {
+               int khz = pstate->base.domain[nv_clk_src_mem];
+               do {
+                       ret = pfb->ram->calc(pfb, khz);
+                       if (ret == 0)
+                               ret = pfb->ram->prog(pfb);
+               } while (ret > 0);
+               pfb->ram->tidy(pfb);
+       }
+
+       return nouveau_cstate_prog(clk, pstate, 0);
+}
+
+static void
+nouveau_pstate_work(struct work_struct *work)
+{
+       struct nouveau_clk *clk = container_of(work, typeof(*clk), work);
+       int pstate;
+
+       if (!atomic_xchg(&clk->waiting, 0))
+               return;
+       clk->pwrsrc = power_supply_is_system_supplied();
+
+       nv_trace(clk, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
+                clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
+                clk->astate, clk->tstate, clk->dstate);
+
+       pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
+       if (clk->state_nr && pstate != -1) {
+               pstate = (pstate < 0) ? clk->astate : pstate;
+               pstate = min(pstate, clk->state_nr - 1 - clk->tstate);
+               pstate = max(pstate, clk->dstate);
+       } else {
+               pstate = clk->pstate = -1;
+       }
+
+       nv_trace(clk, "-> %d\n", pstate);
+       if (pstate != clk->pstate) {
+               int ret = nouveau_pstate_prog(clk, pstate);
+               if (ret) {
+                       nv_error(clk, "error setting pstate %d: %d\n",
+                                pstate, ret);
+               }
+       }
+
+       wake_up_all(&clk->wait);
+       nvkm_notify_get(&clk->pwrsrc_ntfy);
+}
+
+static int
+nouveau_pstate_calc(struct nouveau_clk *clk, bool wait)
+{
+       atomic_set(&clk->waiting, 1);
+       schedule_work(&clk->work);
+       if (wait)
+               wait_event(clk->wait, !atomic_read(&clk->waiting));
+       return 0;
+}
+
+static void
+nouveau_pstate_info(struct nouveau_clk *clk, struct nouveau_pstate *pstate)
+{
+       struct nouveau_domain *clock = clk->domains - 1;
+       struct nouveau_cstate *cstate;
+       char info[3][32] = { "", "", "" };
+       char name[4] = "--";
+       int i = -1;
+
+       if (pstate->pstate != 0xff)
+               snprintf(name, sizeof(name), "%02x", pstate->pstate);
+
+       while ((++clock)->name != nv_clk_src_max) {
+               u32 lo = pstate->base.domain[clock->name];
+               u32 hi = lo;
+               if (hi == 0)
+                       continue;
+
+               nv_debug(clk, "%02x: %10d KHz\n", clock->name, lo);
+               list_for_each_entry(cstate, &pstate->list, head) {
+                       u32 freq = cstate->domain[clock->name];
+                       lo = min(lo, freq);
+                       hi = max(hi, freq);
+                       nv_debug(clk, "%10d KHz\n", freq);
+               }
+
+               if (clock->mname && ++i < ARRAY_SIZE(info)) {
+                       lo /= clock->mdiv;
+                       hi /= clock->mdiv;
+                       if (lo == hi) {
+                               snprintf(info[i], sizeof(info[i]), "%s %d MHz",
+                                        clock->mname, lo);
+                       } else {
+                               snprintf(info[i], sizeof(info[i]),
+                                        "%s %d-%d MHz", clock->mname, lo, hi);
+                       }
+               }
+       }
+
+       nv_info(clk, "%s: %s %s %s\n", name, info[0], info[1], info[2]);
+}
+
+static void
+nouveau_pstate_del(struct nouveau_pstate *pstate)
+{
+       struct nouveau_cstate *cstate, *temp;
+
+       list_for_each_entry_safe(cstate, temp, &pstate->list, head) {
+               nouveau_cstate_del(cstate);
+       }
+
+       list_del(&pstate->head);
+       kfree(pstate);
+}
+
+static int
+nouveau_pstate_new(struct nouveau_clk *clk, int idx)
+{
+       struct nouveau_bios *bios = nouveau_bios(clk);
+       struct nouveau_domain *domain = clk->domains - 1;
+       struct nouveau_pstate *pstate;
+       struct nouveau_cstate *cstate;
+       struct nvbios_cstepE cstepE;
+       struct nvbios_perfE perfE;
+       u8  ver, hdr, cnt, len;
+       u16 data;
+
+       data = nvbios_perfEp(bios, idx, &ver, &hdr, &cnt, &len, &perfE);
+       if (!data)
+               return -EINVAL;
+       if (perfE.pstate == 0xff)
+               return 0;
+
+       pstate = kzalloc(sizeof(*pstate), GFP_KERNEL);
+       cstate = &pstate->base;
+       if (!pstate)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&pstate->list);
+
+       pstate->pstate = perfE.pstate;
+       pstate->fanspeed = perfE.fanspeed;
+       cstate->voltage = perfE.voltage;
+       cstate->domain[nv_clk_src_core] = perfE.core;
+       cstate->domain[nv_clk_src_shader] = perfE.shader;
+       cstate->domain[nv_clk_src_mem] = perfE.memory;
+       cstate->domain[nv_clk_src_vdec] = perfE.vdec;
+       cstate->domain[nv_clk_src_dom6] = perfE.disp;
+
+       while (ver >= 0x40 && (++domain)->name != nv_clk_src_max) {
+               struct nvbios_perfS perfS;
+               u8  sver = ver, shdr = hdr;
+               u32 perfSe = nvbios_perfSp(bios, data, domain->bios,
+                                         &sver, &shdr, cnt, len, &perfS);
+               if (perfSe == 0 || sver != 0x40)
+                       continue;
+
+               if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
+                       perfS.v40.freq = nouveau_clk_adjust(clk, false,
+                                                             pstate->pstate,
+                                                             domain->bios,
+                                                             perfS.v40.freq);
+               }
+
+               cstate->domain[domain->name] = perfS.v40.freq;
+       }
+
+       data = nvbios_cstepEm(bios, pstate->pstate, &ver, &hdr, &cstepE);
+       if (data) {
+               int idx = cstepE.index;
+               do {
+                       nouveau_cstate_new(clk, idx, pstate);
+               } while(idx--);
+       }
+
+       nouveau_pstate_info(clk, pstate);
+       list_add_tail(&pstate->head, &clk->states);
+       clk->state_nr++;
+       return 0;
+}
+
+/******************************************************************************
+ * Adjustment triggers
+ *****************************************************************************/
+static int
+nouveau_clk_ustate_update(struct nouveau_clk *clk, int req)
+{
+       struct nouveau_pstate *pstate;
+       int i = 0;
+
+       if (!clk->allow_reclock)
+               return -ENOSYS;
+
+       if (req != -1 && req != -2) {
+               list_for_each_entry(pstate, &clk->states, head) {
+                       if (pstate->pstate == req)
+                               break;
+                       i++;
+               }
+
+               if (pstate->pstate != req)
+                       return -EINVAL;
+               req = i;
+       }
+
+       return req + 2;
+}
+
+static int
+nouveau_clk_nstate(struct nouveau_clk *clk, const char *mode, int arglen)
+{
+       int ret = 1;
+
+       if (clk->allow_reclock && !strncasecmpz(mode, "auto", arglen))
+               return -2;
+
+       if (strncasecmpz(mode, "disabled", arglen)) {
+               char save = mode[arglen];
+               long v;
+
+               ((char *)mode)[arglen] = '\0';
+               if (!kstrtol(mode, 0, &v)) {
+                       ret = nouveau_clk_ustate_update(clk, v);
+                       if (ret < 0)
+                               ret = 1;
+               }
+               ((char *)mode)[arglen] = save;
+       }
+
+       return ret - 2;
+}
+
+int
+nouveau_clk_ustate(struct nouveau_clk *clk, int req, int pwr)
+{
+       int ret = nouveau_clk_ustate_update(clk, req);
+       if (ret >= 0) {
+               if (ret -= 2, pwr) clk->ustate_ac = ret;
+               else               clk->ustate_dc = ret;
+               return nouveau_pstate_calc(clk, true);
+       }
+       return ret;
+}
+
+int
+nouveau_clk_astate(struct nouveau_clk *clk, int req, int rel, bool wait)
+{
+       if (!rel) clk->astate  = req;
+       if ( rel) clk->astate += rel;
+       clk->astate = min(clk->astate, clk->state_nr - 1);
+       clk->astate = max(clk->astate, 0);
+       return nouveau_pstate_calc(clk, wait);
+}
+
+int
+nouveau_clk_tstate(struct nouveau_clk *clk, int req, int rel)
+{
+       if (!rel) clk->tstate  = req;
+       if ( rel) clk->tstate += rel;
+       clk->tstate = min(clk->tstate, 0);
+       clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
+       return nouveau_pstate_calc(clk, true);
+}
+
+int
+nouveau_clk_dstate(struct nouveau_clk *clk, int req, int rel)
+{
+       if (!rel) clk->dstate  = req;
+       if ( rel) clk->dstate += rel;
+       clk->dstate = min(clk->dstate, clk->state_nr - 1);
+       clk->dstate = max(clk->dstate, 0);
+       return nouveau_pstate_calc(clk, true);
+}
+
+static int
+nouveau_clk_pwrsrc(struct nvkm_notify *notify)
+{
+       struct nouveau_clk *clk =
+               container_of(notify, typeof(*clk), pwrsrc_ntfy);
+       nouveau_pstate_calc(clk, false);
+       return NVKM_NOTIFY_DROP;
+}
+
+/******************************************************************************
+ * subdev base class implementation
+ *****************************************************************************/
+
+int
+_nouveau_clk_fini(struct nouveau_object *object, bool suspend)
+{
+       struct nouveau_clk *clk = (void *)object;
+       nvkm_notify_put(&clk->pwrsrc_ntfy);
+       return nouveau_subdev_fini(&clk->base, suspend);
+}
+
+int
+_nouveau_clk_init(struct nouveau_object *object)
+{
+       struct nouveau_clk *clk = (void *)object;
+       struct nouveau_domain *clock = clk->domains;
+       int ret;
+
+       ret = nouveau_subdev_init(&clk->base);
+       if (ret)
+               return ret;
+
+       memset(&clk->bstate, 0x00, sizeof(clk->bstate));
+       INIT_LIST_HEAD(&clk->bstate.list);
+       clk->bstate.pstate = 0xff;
+
+       while (clock->name != nv_clk_src_max) {
+               ret = clk->read(clk, clock->name);
+               if (ret < 0) {
+                       nv_error(clk, "%02x freq unknown\n", clock->name);
+                       return ret;
+               }
+               clk->bstate.base.domain[clock->name] = ret;
+               clock++;
+       }
+
+       nouveau_pstate_info(clk, &clk->bstate);
+
+       clk->astate = clk->state_nr - 1;
+       clk->tstate = 0;
+       clk->dstate = 0;
+       clk->pstate = -1;
+       nouveau_pstate_calc(clk, true);
+       return 0;
+}
+
+void
+_nouveau_clk_dtor(struct nouveau_object *object)
+{
+       struct nouveau_clk *clk = (void *)object;
+       struct nouveau_pstate *pstate, *temp;
+
+       nvkm_notify_fini(&clk->pwrsrc_ntfy);
+
+       list_for_each_entry_safe(pstate, temp, &clk->states, head) {
+               nouveau_pstate_del(pstate);
+       }
+
+       nouveau_subdev_destroy(&clk->base);
+}
+
+int
+nouveau_clk_create_(struct nouveau_object *parent,
+                     struct nouveau_object *engine,
+                     struct nouveau_oclass *oclass,
+                     struct nouveau_domain *clocks,
+                     struct nouveau_pstate *pstates, int nb_pstates,
+                     bool allow_reclock,
+                     int length, void **object)
+{
+       struct nouveau_device *device = nv_device(parent);
+       struct nouveau_clk *clk;
+       int ret, idx, arglen;
+       const char *mode;
+
+       ret = nouveau_subdev_create_(parent, engine, oclass, 0, "CLK",
+                                    "clock", length, object);
+       clk = *object;
+       if (ret)
+               return ret;
+
+       INIT_LIST_HEAD(&clk->states);
+       clk->domains = clocks;
+       clk->ustate_ac = -1;
+       clk->ustate_dc = -1;
+
+       INIT_WORK(&clk->work, nouveau_pstate_work);
+       init_waitqueue_head(&clk->wait);
+       atomic_set(&clk->waiting, 0);
+
+       /* If no pstates are provided, try and fetch them from the BIOS */
+       if (!pstates) {
+               idx = 0;
+               do {
+                       ret = nouveau_pstate_new(clk, idx++);
+               } while (ret == 0);
+       } else {
+               for (idx = 0; idx < nb_pstates; idx++)
+                       list_add_tail(&pstates[idx].head, &clk->states);
+               clk->state_nr = nb_pstates;
+       }
+
+       clk->allow_reclock = allow_reclock;
+
+       ret = nvkm_notify_init(NULL, &device->event, nouveau_clk_pwrsrc, true,
+                              NULL, 0, 0, &clk->pwrsrc_ntfy);
+       if (ret)
+               return ret;
+
+       mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
+       if (mode) {
+               clk->ustate_ac = nouveau_clk_nstate(clk, mode, arglen);
+               clk->ustate_dc = nouveau_clk_nstate(clk, mode, arglen);
+       }
+
+       mode = nouveau_stropt(device->cfgopt, "NvClkModeAC", &arglen);
+       if (mode)
+               clk->ustate_ac = nouveau_clk_nstate(clk, mode, arglen);
+
+       mode = nouveau_stropt(device->cfgopt, "NvClkModeDC", &arglen);
+       if (mode)
+               clk->ustate_dc = nouveau_clk_nstate(clk, mode, arglen);
+
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c
new file mode 100644 (file)
index 0000000..4529ba2
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c
+ *
+ */
+
+#define MHZ (1000 * 1000)
+
+#define MASK(w)        ((1 << w) - 1)
+
+#define SYS_GPCPLL_CFG_BASE                    0x00137000
+#define GPC_BCASE_GPCPLL_CFG_BASE              0x00132800
+
+#define GPCPLL_CFG             (SYS_GPCPLL_CFG_BASE + 0)
+#define GPCPLL_CFG_ENABLE      BIT(0)
+#define GPCPLL_CFG_IDDQ                BIT(1)
+#define GPCPLL_CFG_LOCK_DET_OFF        BIT(4)
+#define GPCPLL_CFG_LOCK                BIT(17)
+
+#define GPCPLL_COEFF           (SYS_GPCPLL_CFG_BASE + 4)
+#define GPCPLL_COEFF_M_SHIFT   0
+#define GPCPLL_COEFF_M_WIDTH   8
+#define GPCPLL_COEFF_N_SHIFT   8
+#define GPCPLL_COEFF_N_WIDTH   8
+#define GPCPLL_COEFF_P_SHIFT   16
+#define GPCPLL_COEFF_P_WIDTH   6
+
+#define GPCPLL_CFG2                    (SYS_GPCPLL_CFG_BASE + 0xc)
+#define GPCPLL_CFG2_SETUP2_SHIFT       16
+#define GPCPLL_CFG2_PLL_STEPA_SHIFT    24
+
+#define GPCPLL_CFG3                    (SYS_GPCPLL_CFG_BASE + 0x18)
+#define GPCPLL_CFG3_PLL_STEPB_SHIFT    16
+
+#define GPCPLL_NDIV_SLOWDOWN                   (SYS_GPCPLL_CFG_BASE + 0x1c)
+#define GPCPLL_NDIV_SLOWDOWN_NDIV_LO_SHIFT     0
+#define GPCPLL_NDIV_SLOWDOWN_NDIV_MID_SHIFT    8
+#define GPCPLL_NDIV_SLOWDOWN_STEP_SIZE_LO2MID_SHIFT    16
+#define GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT  22
+#define GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT  31
+
+#define SEL_VCO                                (SYS_GPCPLL_CFG_BASE + 0x100)
+#define SEL_VCO_GPC2CLK_OUT_SHIFT      0
+
+#define GPC2CLK_OUT                    (SYS_GPCPLL_CFG_BASE + 0x250)
+#define GPC2CLK_OUT_SDIV14_INDIV4_WIDTH        1
+#define GPC2CLK_OUT_SDIV14_INDIV4_SHIFT        31
+#define GPC2CLK_OUT_SDIV14_INDIV4_MODE 1
+#define GPC2CLK_OUT_VCODIV_WIDTH       6
+#define GPC2CLK_OUT_VCODIV_SHIFT       8
+#define GPC2CLK_OUT_VCODIV1            0
+#define GPC2CLK_OUT_VCODIV_MASK                (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << \
+                                       GPC2CLK_OUT_VCODIV_SHIFT)
+#define        GPC2CLK_OUT_BYPDIV_WIDTH        6
+#define GPC2CLK_OUT_BYPDIV_SHIFT       0
+#define GPC2CLK_OUT_BYPDIV31           0x3c
+#define GPC2CLK_OUT_INIT_MASK  ((MASK(GPC2CLK_OUT_SDIV14_INDIV4_WIDTH) << \
+               GPC2CLK_OUT_SDIV14_INDIV4_SHIFT)\
+               | (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << GPC2CLK_OUT_VCODIV_SHIFT)\
+               | (MASK(GPC2CLK_OUT_BYPDIV_WIDTH) << GPC2CLK_OUT_BYPDIV_SHIFT))
+#define GPC2CLK_OUT_INIT_VAL   ((GPC2CLK_OUT_SDIV14_INDIV4_MODE << \
+               GPC2CLK_OUT_SDIV14_INDIV4_SHIFT) \
+               | (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT) \
+               | (GPC2CLK_OUT_BYPDIV31 << GPC2CLK_OUT_BYPDIV_SHIFT))
+
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG  (GPC_BCASE_GPCPLL_CFG_BASE + 0xa0)
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT    24
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
+           (0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
+
+#include <subdev/clk.h>
+#include <subdev/timer.h>
+
+#ifdef __KERNEL__
+#include <nouveau_platform.h>
+#endif
+
+static const u8 pl_to_div[] = {
+/* PL:   0, 1, 2, 3, 4, 5, 6,  7,  8,  9, 10, 11, 12, 13, 14 */
+/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
+};
+
+/* All frequencies in Mhz */
+struct gk20a_clk_pllg_params {
+       u32 min_vco, max_vco;
+       u32 min_u, max_u;
+       u32 min_m, max_m;
+       u32 min_n, max_n;
+       u32 min_pl, max_pl;
+};
+
+static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
+       .min_vco = 1000, .max_vco = 2064,
+       .min_u = 12, .max_u = 38,
+       .min_m = 1, .max_m = 255,
+       .min_n = 8, .max_n = 255,
+       .min_pl = 1, .max_pl = 32,
+};
+
+struct gk20a_clk_priv {
+       struct nouveau_clk base;
+       const struct gk20a_clk_pllg_params *params;
+       u32 m, n, pl;
+       u32 parent_rate;
+};
+#define to_gk20a_clk(base) container_of(base, struct gk20a_clk_priv, base)
+
+static void
+gk20a_pllg_read_mnp(struct gk20a_clk_priv *priv)
+{
+       u32 val;
+
+       val = nv_rd32(priv, GPCPLL_COEFF);
+       priv->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+       priv->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH);
+       priv->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
+}
+
+static u32
+gk20a_pllg_calc_rate(struct gk20a_clk_priv *priv)
+{
+       u32 rate;
+       u32 divider;
+
+       rate = priv->parent_rate * priv->n;
+       divider = priv->m * pl_to_div[priv->pl];
+       do_div(rate, divider);
+
+       return rate / 2;
+}
+
+static int
+gk20a_pllg_calc_mnp(struct gk20a_clk_priv *priv, unsigned long rate)
+{
+       u32 target_clk_f, ref_clk_f, target_freq;
+       u32 min_vco_f, max_vco_f;
+       u32 low_pl, high_pl, best_pl;
+       u32 target_vco_f, vco_f;
+       u32 best_m, best_n;
+       u32 u_f;
+       u32 m, n, n2;
+       u32 delta, lwv, best_delta = ~0;
+       u32 pl;
+
+       target_clk_f = rate * 2 / MHZ;
+       ref_clk_f = priv->parent_rate / MHZ;
+
+       max_vco_f = priv->params->max_vco;
+       min_vco_f = priv->params->min_vco;
+       best_m = priv->params->max_m;
+       best_n = priv->params->min_n;
+       best_pl = priv->params->min_pl;
+
+       target_vco_f = target_clk_f + target_clk_f / 50;
+       if (max_vco_f < target_vco_f)
+               max_vco_f = target_vco_f;
+
+       /* min_pl <= high_pl <= max_pl */
+       high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
+       high_pl = min(high_pl, priv->params->max_pl);
+       high_pl = max(high_pl, priv->params->min_pl);
+
+       /* min_pl <= low_pl <= max_pl */
+       low_pl = min_vco_f / target_vco_f;
+       low_pl = min(low_pl, priv->params->max_pl);
+       low_pl = max(low_pl, priv->params->min_pl);
+
+       /* Find Indices of high_pl and low_pl */
+       for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
+               if (pl_to_div[pl] >= low_pl) {
+                       low_pl = pl;
+                       break;
+               }
+       }
+       for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
+               if (pl_to_div[pl] >= high_pl) {
+                       high_pl = pl;
+                       break;
+               }
+       }
+
+       nv_debug(priv, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
+                pl_to_div[low_pl], high_pl, pl_to_div[high_pl]);
+
+       /* Select lowest possible VCO */
+       for (pl = low_pl; pl <= high_pl; pl++) {
+               target_vco_f = target_clk_f * pl_to_div[pl];
+               for (m = priv->params->min_m; m <= priv->params->max_m; m++) {
+                       u_f = ref_clk_f / m;
+
+                       if (u_f < priv->params->min_u)
+                               break;
+                       if (u_f > priv->params->max_u)
+                               continue;
+
+                       n = (target_vco_f * m) / ref_clk_f;
+                       n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f;
+
+                       if (n > priv->params->max_n)
+                               break;
+
+                       for (; n <= n2; n++) {
+                               if (n < priv->params->min_n)
+                                       continue;
+                               if (n > priv->params->max_n)
+                                       break;
+
+                               vco_f = ref_clk_f * n / m;
+
+                               if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
+                                       lwv = (vco_f + (pl_to_div[pl] / 2))
+                                               / pl_to_div[pl];
+                                       delta = abs(lwv - target_clk_f);
+
+                                       if (delta < best_delta) {
+                                               best_delta = delta;
+                                               best_m = m;
+                                               best_n = n;
+                                               best_pl = pl;
+
+                                               if (best_delta == 0)
+                                                       goto found_match;
+                                       }
+                               }
+                       }
+               }
+       }
+
+found_match:
+       WARN_ON(best_delta == ~0);
+
+       if (best_delta != 0)
+               nv_debug(priv, "no best match for target @ %dMHz on gpc_pll",
+                        target_clk_f);
+
+       priv->m = best_m;
+       priv->n = best_n;
+       priv->pl = best_pl;
+
+       target_freq = gk20a_pllg_calc_rate(priv) / MHZ;
+
+       nv_debug(priv, "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n",
+                target_freq, priv->m, priv->n, priv->pl, pl_to_div[priv->pl]);
+
+       return 0;
+}
+
+static int
+gk20a_pllg_slide(struct gk20a_clk_priv *priv, u32 n)
+{
+       u32 val;
+       int ramp_timeout;
+
+       /* get old coefficients */
+       val = nv_rd32(priv, GPCPLL_COEFF);
+       /* do nothing if NDIV is the same */
+       if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH)))
+               return 0;
+
+       /* setup */
+       nv_mask(priv, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
+               0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT);
+       nv_mask(priv, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
+               0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT);
+
+       /* pll slowdown mode */
+       nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
+               BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
+               BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
+
+       /* new ndiv ready for ramp */
+       val = nv_rd32(priv, GPCPLL_COEFF);
+       val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT);
+       val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
+       udelay(1);
+       nv_wr32(priv, GPCPLL_COEFF, val);
+
+       /* dynamic ramp to new ndiv */
+       val = nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
+       val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT;
+       udelay(1);
+       nv_wr32(priv, GPCPLL_NDIV_SLOWDOWN, val);
+
+       for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) {
+               udelay(1);
+               val = nv_rd32(priv, GPC_BCAST_NDIV_SLOWDOWN_DEBUG);
+               if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK)
+                       break;
+       }
+
+       /* exit slowdown mode */
+       nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
+               BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) |
+               BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
+       nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
+
+       if (ramp_timeout <= 0) {
+               nv_error(priv, "gpcpll dynamic ramp timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static void
+_gk20a_pllg_enable(struct gk20a_clk_priv *priv)
+{
+       nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
+       nv_rd32(priv, GPCPLL_CFG);
+}
+
+static void
+_gk20a_pllg_disable(struct gk20a_clk_priv *priv)
+{
+       nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
+       nv_rd32(priv, GPCPLL_CFG);
+}
+
+static int
+_gk20a_pllg_program_mnp(struct gk20a_clk_priv *priv, bool allow_slide)
+{
+       u32 val, cfg;
+       u32 m_old, pl_old, n_lo;
+
+       /* get old coefficients */
+       val = nv_rd32(priv, GPCPLL_COEFF);
+       m_old = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+       pl_old = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
+
+       /* do NDIV slide if there is no change in M and PL */
+       cfg = nv_rd32(priv, GPCPLL_CFG);
+       if (allow_slide && priv->m == m_old && priv->pl == pl_old &&
+           (cfg & GPCPLL_CFG_ENABLE)) {
+               return gk20a_pllg_slide(priv, priv->n);
+       }
+
+       /* slide down to NDIV_LO */
+       n_lo = DIV_ROUND_UP(m_old * priv->params->min_vco,
+                           priv->parent_rate / MHZ);
+       if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) {
+               int ret = gk20a_pllg_slide(priv, n_lo);
+
+               if (ret)
+                       return ret;
+       }
+
+       /* split FO-to-bypass jump in halfs by setting out divider 1:2 */
+       nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
+               0x2 << GPC2CLK_OUT_VCODIV_SHIFT);
+
+       /* put PLL in bypass before programming it */
+       val = nv_rd32(priv, SEL_VCO);
+       val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
+       udelay(2);
+       nv_wr32(priv, SEL_VCO, val);
+
+       /* get out from IDDQ */
+       val = nv_rd32(priv, GPCPLL_CFG);
+       if (val & GPCPLL_CFG_IDDQ) {
+               val &= ~GPCPLL_CFG_IDDQ;
+               nv_wr32(priv, GPCPLL_CFG, val);
+               nv_rd32(priv, GPCPLL_CFG);
+               udelay(2);
+       }
+
+       _gk20a_pllg_disable(priv);
+
+       nv_debug(priv, "%s: m=%d n=%d pl=%d\n", __func__, priv->m, priv->n,
+                priv->pl);
+
+       n_lo = DIV_ROUND_UP(priv->m * priv->params->min_vco,
+                           priv->parent_rate / MHZ);
+       val = priv->m << GPCPLL_COEFF_M_SHIFT;
+       val |= (allow_slide ? n_lo : priv->n) << GPCPLL_COEFF_N_SHIFT;
+       val |= priv->pl << GPCPLL_COEFF_P_SHIFT;
+       nv_wr32(priv, GPCPLL_COEFF, val);
+
+       _gk20a_pllg_enable(priv);
+
+       val = nv_rd32(priv, GPCPLL_CFG);
+       if (val & GPCPLL_CFG_LOCK_DET_OFF) {
+               val &= ~GPCPLL_CFG_LOCK_DET_OFF;
+               nv_wr32(priv, GPCPLL_CFG, val);
+       }
+
+       if (!nouveau_timer_wait_eq(priv, 300000, GPCPLL_CFG, GPCPLL_CFG_LOCK,
+                                  GPCPLL_CFG_LOCK)) {
+               nv_error(priv, "%s: timeout waiting for pllg lock\n", __func__);
+               return -ETIMEDOUT;
+       }
+
+       /* switch to VCO mode */
+       nv_mask(priv, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
+
+       /* restore out divider 1:1 */
+       val = nv_rd32(priv, GPC2CLK_OUT);
+       val &= ~GPC2CLK_OUT_VCODIV_MASK;
+       udelay(2);
+       nv_wr32(priv, GPC2CLK_OUT, val);
+
+       /* slide up to new NDIV */
+       return allow_slide ? gk20a_pllg_slide(priv, priv->n) : 0;
+}
+
+static int
+gk20a_pllg_program_mnp(struct gk20a_clk_priv *priv)
+{
+       int err;
+
+       err = _gk20a_pllg_program_mnp(priv, true);
+       if (err)
+               err = _gk20a_pllg_program_mnp(priv, false);
+
+       return err;
+}
+
+static void
+gk20a_pllg_disable(struct gk20a_clk_priv *priv)
+{
+       u32 val;
+
+       /* slide to VCO min */
+       val = nv_rd32(priv, GPCPLL_CFG);
+       if (val & GPCPLL_CFG_ENABLE) {
+               u32 coeff, m, n_lo;
+
+               coeff = nv_rd32(priv, GPCPLL_COEFF);
+               m = (coeff >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+               n_lo = DIV_ROUND_UP(m * priv->params->min_vco,
+                                   priv->parent_rate / MHZ);
+               gk20a_pllg_slide(priv, n_lo);
+       }
+
+       /* put PLL in bypass before disabling it */
+       nv_mask(priv, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
+
+       _gk20a_pllg_disable(priv);
+}
+
+#define GK20A_CLK_GPC_MDIV 1000
+
+static struct nouveau_domain
+gk20a_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
+       { nv_clk_src_max }
+};
+
+static struct nouveau_pstate
+gk20a_pstates[] = {
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 72000,
+                       .voltage = 0,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 108000,
+                       .voltage = 1,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 180000,
+                       .voltage = 2,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 252000,
+                       .voltage = 3,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 324000,
+                       .voltage = 4,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 396000,
+                       .voltage = 5,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 468000,
+                       .voltage = 6,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 540000,
+                       .voltage = 7,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 612000,
+                       .voltage = 8,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 648000,
+                       .voltage = 9,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 684000,
+                       .voltage = 10,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 708000,
+                       .voltage = 11,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 756000,
+                       .voltage = 12,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 804000,
+                       .voltage = 13,
+               },
+       },
+       {
+               .base = {
+                       .domain[nv_clk_src_gpc] = 852000,
+                       .voltage = 14,
+               },
+       },
+};
+
+static int
+gk20a_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct gk20a_clk_priv *priv = (void *)clk;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(clk)->crystal;
+       case nv_clk_src_gpc:
+               gk20a_pllg_read_mnp(priv);
+               return gk20a_pllg_calc_rate(priv) / GK20A_CLK_GPC_MDIV;
+       default:
+               nv_error(clk, "invalid clock source %d\n", src);
+               return -EINVAL;
+       }
+}
+
+static int
+gk20a_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct gk20a_clk_priv *priv = (void *)clk;
+
+       return gk20a_pllg_calc_mnp(priv, cstate->domain[nv_clk_src_gpc] *
+                                        GK20A_CLK_GPC_MDIV);
+}
+
+static int
+gk20a_clk_prog(struct nouveau_clk *clk)
+{
+       struct gk20a_clk_priv *priv = (void *)clk;
+
+       return gk20a_pllg_program_mnp(priv);
+}
+
+static void
+gk20a_clk_tidy(struct nouveau_clk *clk)
+{
+}
+
+static int
+gk20a_clk_fini(struct nouveau_object *object, bool suspend)
+{
+       struct gk20a_clk_priv *priv = (void *)object;
+       int ret;
+
+       ret = nouveau_clk_fini(&priv->base, false);
+
+       gk20a_pllg_disable(priv);
+
+       return ret;
+}
+
+static int
+gk20a_clk_init(struct nouveau_object *object)
+{
+       struct gk20a_clk_priv *priv = (void *)object;
+       int ret;
+
+       nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL);
+
+       ret = nouveau_clk_init(&priv->base);
+       if (ret)
+               return ret;
+
+       ret = gk20a_clk_prog(&priv->base);
+       if (ret) {
+               nv_error(priv, "cannot initialize clock\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int
+gk20a_clk_ctor(struct nouveau_object *parent,  struct nouveau_object *engine,
+                struct nouveau_oclass *oclass, void *data, u32 size,
+                struct nouveau_object **pobject)
+{
+       struct gk20a_clk_priv *priv;
+       struct nouveau_platform_device *plat;
+       int ret;
+       int i;
+
+       /* Finish initializing the pstates */
+       for (i = 0; i < ARRAY_SIZE(gk20a_pstates); i++) {
+               INIT_LIST_HEAD(&gk20a_pstates[i].list);
+               gk20a_pstates[i].pstate = i + 1;
+       }
+
+       ret = nouveau_clk_create(parent, engine, oclass, gk20a_domains,
+                       gk20a_pstates, ARRAY_SIZE(gk20a_pstates), true, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->params = &gk20a_pllg_params;
+
+       plat = nv_device_to_platform(nv_device(parent));
+       priv->parent_rate = clk_get_rate(plat->gpu->clk);
+       nv_info(priv, "parent clock rate: %d Mhz\n", priv->parent_rate / MHZ);
+
+       priv->base.read = gk20a_clk_read;
+       priv->base.calc = gk20a_clk_calc;
+       priv->base.prog = gk20a_clk_prog;
+       priv->base.tidy = gk20a_clk_tidy;
+
+       return 0;
+}
+
+struct nouveau_oclass
+gk20a_clk_oclass = {
+       .handle = NV_SUBDEV(CLK, 0xea),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gk20a_clk_ctor,
+               .dtor = _nouveau_subdev_dtor,
+               .init = gk20a_clk_init,
+               .fini = gk20a_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv04.c
new file mode 100644 (file)
index 0000000..de68f2f
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/clk.h>
+#include <subdev/devinit/nv04.h>
+
+#include "pll.h"
+
+struct nv04_clk_priv {
+       struct nouveau_clk base;
+};
+
+int
+nv04_clk_pll_calc(struct nouveau_clk *clock, struct nvbios_pll *info,
+                   int clk, struct nouveau_pll_vals *pv)
+{
+       int N1, M1, N2, M2, P;
+       int ret = nv04_pll_calc(nv_subdev(clock), info, clk, &N1, &M1, &N2, &M2, &P);
+       if (ret) {
+               pv->refclk = info->refclk;
+               pv->N1 = N1;
+               pv->M1 = M1;
+               pv->N2 = N2;
+               pv->M2 = M2;
+               pv->log2P = P;
+       }
+       return ret;
+}
+
+int
+nv04_clk_pll_prog(struct nouveau_clk *clk, u32 reg1,
+                   struct nouveau_pll_vals *pv)
+{
+       struct nouveau_devinit *devinit = nouveau_devinit(clk);
+       int cv = nouveau_bios(clk)->version.chip;
+
+       if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
+           cv >= 0x40) {
+               if (reg1 > 0x405c)
+                       setPLL_double_highregs(devinit, reg1, pv);
+               else
+                       setPLL_double_lowregs(devinit, reg1, pv);
+       } else
+               setPLL_single(devinit, reg1, pv);
+
+       return 0;
+}
+
+static struct nouveau_domain
+nv04_domain[] = {
+       { nv_clk_src_max }
+};
+
+static int
+nv04_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nv04_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, nv04_domain, NULL, 0,
+                                  false, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.pll_calc = nv04_clk_pll_calc;
+       priv->base.pll_prog = nv04_clk_pll_prog;
+       return 0;
+}
+
+struct nouveau_oclass
+nv04_clk_oclass = {
+       .handle = NV_SUBDEV(CLK, 0x04),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv40.c
new file mode 100644 (file)
index 0000000..460ca4a
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/clk.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+
+#include "pll.h"
+
+struct nv40_clk_priv {
+       struct nouveau_clk base;
+       u32 ctrl;
+       u32 npll_ctrl;
+       u32 npll_coef;
+       u32 spll;
+};
+
+static struct nouveau_domain
+nv40_domain[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
+       { nv_clk_src_max }
+};
+
+static u32
+read_pll_1(struct nv40_clk_priv *priv, u32 reg)
+{
+       u32 ctrl = nv_rd32(priv, reg + 0x00);
+       int P = (ctrl & 0x00070000) >> 16;
+       int N = (ctrl & 0x0000ff00) >> 8;
+       int M = (ctrl & 0x000000ff) >> 0;
+       u32 ref = 27000, clk = 0;
+
+       if (ctrl & 0x80000000)
+               clk = ref * N / M;
+
+       return clk >> P;
+}
+
+static u32
+read_pll_2(struct nv40_clk_priv *priv, u32 reg)
+{
+       u32 ctrl = nv_rd32(priv, reg + 0x00);
+       u32 coef = nv_rd32(priv, reg + 0x04);
+       int N2 = (coef & 0xff000000) >> 24;
+       int M2 = (coef & 0x00ff0000) >> 16;
+       int N1 = (coef & 0x0000ff00) >> 8;
+       int M1 = (coef & 0x000000ff) >> 0;
+       int P = (ctrl & 0x00070000) >> 16;
+       u32 ref = 27000, clk = 0;
+
+       if ((ctrl & 0x80000000) && M1) {
+               clk = ref * N1 / M1;
+               if ((ctrl & 0x40000100) == 0x40000000) {
+                       if (M2)
+                               clk = clk * N2 / M2;
+                       else
+                               clk = 0;
+               }
+       }
+
+       return clk >> P;
+}
+
+static u32
+read_clk(struct nv40_clk_priv *priv, u32 src)
+{
+       switch (src) {
+       case 3:
+               return read_pll_2(priv, 0x004000);
+       case 2:
+               return read_pll_1(priv, 0x004008);
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int
+nv40_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct nv40_clk_priv *priv = (void *)clk;
+       u32 mast = nv_rd32(priv, 0x00c040);
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_href:
+               return 100000; /*XXX: PCIE/AGP differ*/
+       case nv_clk_src_core:
+               return read_clk(priv, (mast & 0x00000003) >> 0);
+       case nv_clk_src_shader:
+               return read_clk(priv, (mast & 0x00000030) >> 4);
+       case nv_clk_src_mem:
+               return read_pll_2(priv, 0x4020);
+       default:
+               break;
+       }
+
+       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
+       return -EINVAL;
+}
+
+static int
+nv40_clk_calc_pll(struct nv40_clk_priv *priv, u32 reg, u32 clk,
+                   int *N1, int *M1, int *N2, int *M2, int *log2P)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll pll;
+       int ret;
+
+       ret = nvbios_pll_parse(bios, reg, &pll);
+       if (ret)
+               return ret;
+
+       if (clk < pll.vco1.max_freq)
+               pll.vco2.max_freq = 0;
+
+       ret = nv04_pll_calc(nv_subdev(priv), &pll, clk, N1, M1, N2, M2, log2P);
+       if (ret == 0)
+               return -ERANGE;
+       return ret;
+}
+
+static int
+nv40_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct nv40_clk_priv *priv = (void *)clk;
+       int gclk = cstate->domain[nv_clk_src_core];
+       int sclk = cstate->domain[nv_clk_src_shader];
+       int N1, M1, N2, M2, log2P;
+       int ret;
+
+       /* core/geometric clock */
+       ret = nv40_clk_calc_pll(priv, 0x004000, gclk,
+                                &N1, &M1, &N2, &M2, &log2P);
+       if (ret < 0)
+               return ret;
+
+       if (N2 == M2) {
+               priv->npll_ctrl = 0x80000100 | (log2P << 16);
+               priv->npll_coef = (N1 << 8) | M1;
+       } else {
+               priv->npll_ctrl = 0xc0000000 | (log2P << 16);
+               priv->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
+       }
+
+       /* use the second pll for shader/rop clock, if it differs from core */
+       if (sclk && sclk != gclk) {
+               ret = nv40_clk_calc_pll(priv, 0x004008, sclk,
+                                        &N1, &M1, NULL, NULL, &log2P);
+               if (ret < 0)
+                       return ret;
+
+               priv->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
+               priv->ctrl = 0x00000223;
+       } else {
+               priv->spll = 0x00000000;
+               priv->ctrl = 0x00000333;
+       }
+
+       return 0;
+}
+
+static int
+nv40_clk_prog(struct nouveau_clk *clk)
+{
+       struct nv40_clk_priv *priv = (void *)clk;
+       nv_mask(priv, 0x00c040, 0x00000333, 0x00000000);
+       nv_wr32(priv, 0x004004, priv->npll_coef);
+       nv_mask(priv, 0x004000, 0xc0070100, priv->npll_ctrl);
+       nv_mask(priv, 0x004008, 0xc007ffff, priv->spll);
+       mdelay(5);
+       nv_mask(priv, 0x00c040, 0x00000333, priv->ctrl);
+       return 0;
+}
+
+static void
+nv40_clk_tidy(struct nouveau_clk *clk)
+{
+}
+
+static int
+nv40_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nv40_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, nv40_domain, NULL, 0,
+                                  true, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.pll_calc = nv04_clk_pll_calc;
+       priv->base.pll_prog = nv04_clk_pll_prog;
+       priv->base.read = nv40_clk_read;
+       priv->base.calc = nv40_clk_calc;
+       priv->base.prog = nv40_clk_prog;
+       priv->base.tidy = nv40_clk_tidy;
+       return 0;
+}
+
+struct nouveau_oclass
+nv40_clk_oclass = {
+       .handle = NV_SUBDEV(CLK, 0x40),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv40_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c
new file mode 100644 (file)
index 0000000..3c462a2
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+
+#include "nv50.h"
+#include "pll.h"
+#include "seq.h"
+
+static u32
+read_div(struct nv50_clk_priv *priv)
+{
+       switch (nv_device(priv)->chipset) {
+       case 0x50: /* it exists, but only has bit 31, not the dividers.. */
+       case 0x84:
+       case 0x86:
+       case 0x98:
+       case 0xa0:
+               return nv_rd32(priv, 0x004700);
+       case 0x92:
+       case 0x94:
+       case 0x96:
+               return nv_rd32(priv, 0x004800);
+       default:
+               return 0x00000000;
+       }
+}
+
+static u32
+read_pll_src(struct nv50_clk_priv *priv, u32 base)
+{
+       struct nouveau_clk *clk = &priv->base;
+       u32 coef, ref = clk->read(clk, nv_clk_src_crystal);
+       u32 rsel = nv_rd32(priv, 0x00e18c);
+       int P, N, M, id;
+
+       switch (nv_device(priv)->chipset) {
+       case 0x50:
+       case 0xa0:
+               switch (base) {
+               case 0x4020:
+               case 0x4028: id = !!(rsel & 0x00000004); break;
+               case 0x4008: id = !!(rsel & 0x00000008); break;
+               case 0x4030: id = 0; break;
+               default:
+                       nv_error(priv, "ref: bad pll 0x%06x\n", base);
+                       return 0;
+               }
+
+               coef = nv_rd32(priv, 0x00e81c + (id * 0x0c));
+               ref *=  (coef & 0x01000000) ? 2 : 4;
+               P    =  (coef & 0x00070000) >> 16;
+               N    = ((coef & 0x0000ff00) >> 8) + 1;
+               M    = ((coef & 0x000000ff) >> 0) + 1;
+               break;
+       case 0x84:
+       case 0x86:
+       case 0x92:
+               coef = nv_rd32(priv, 0x00e81c);
+               P    = (coef & 0x00070000) >> 16;
+               N    = (coef & 0x0000ff00) >> 8;
+               M    = (coef & 0x000000ff) >> 0;
+               break;
+       case 0x94:
+       case 0x96:
+       case 0x98:
+               rsel = nv_rd32(priv, 0x00c050);
+               switch (base) {
+               case 0x4020: rsel = (rsel & 0x00000003) >> 0; break;
+               case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break;
+               case 0x4028: rsel = (rsel & 0x00001800) >> 11; break;
+               case 0x4030: rsel = 3; break;
+               default:
+                       nv_error(priv, "ref: bad pll 0x%06x\n", base);
+                       return 0;
+               }
+
+               switch (rsel) {
+               case 0: id = 1; break;
+               case 1: return clk->read(clk, nv_clk_src_crystal);
+               case 2: return clk->read(clk, nv_clk_src_href);
+               case 3: id = 0; break;
+               }
+
+               coef =  nv_rd32(priv, 0x00e81c + (id * 0x28));
+               P    = (nv_rd32(priv, 0x00e824 + (id * 0x28)) >> 16) & 7;
+               P   += (coef & 0x00070000) >> 16;
+               N    = (coef & 0x0000ff00) >> 8;
+               M    = (coef & 0x000000ff) >> 0;
+               break;
+       default:
+               BUG_ON(1);
+       }
+
+       if (M)
+               return (ref * N / M) >> P;
+       return 0;
+}
+
+static u32
+read_pll_ref(struct nv50_clk_priv *priv, u32 base)
+{
+       struct nouveau_clk *clk = &priv->base;
+       u32 src, mast = nv_rd32(priv, 0x00c040);
+
+       switch (base) {
+       case 0x004028:
+               src = !!(mast & 0x00200000);
+               break;
+       case 0x004020:
+               src = !!(mast & 0x00400000);
+               break;
+       case 0x004008:
+               src = !!(mast & 0x00010000);
+               break;
+       case 0x004030:
+               src = !!(mast & 0x02000000);
+               break;
+       case 0x00e810:
+               return clk->read(clk, nv_clk_src_crystal);
+       default:
+               nv_error(priv, "bad pll 0x%06x\n", base);
+               return 0;
+       }
+
+       if (src)
+               return clk->read(clk, nv_clk_src_href);
+       return read_pll_src(priv, base);
+}
+
+static u32
+read_pll(struct nv50_clk_priv *priv, u32 base)
+{
+       struct nouveau_clk *clk = &priv->base;
+       u32 mast = nv_rd32(priv, 0x00c040);
+       u32 ctrl = nv_rd32(priv, base + 0);
+       u32 coef = nv_rd32(priv, base + 4);
+       u32 ref = read_pll_ref(priv, base);
+       u32 freq = 0;
+       int N1, N2, M1, M2;
+
+       if (base == 0x004028 && (mast & 0x00100000)) {
+               /* wtf, appears to only disable post-divider on nva0 */
+               if (nv_device(priv)->chipset != 0xa0)
+                       return clk->read(clk, nv_clk_src_dom6);
+       }
+
+       N2 = (coef & 0xff000000) >> 24;
+       M2 = (coef & 0x00ff0000) >> 16;
+       N1 = (coef & 0x0000ff00) >> 8;
+       M1 = (coef & 0x000000ff);
+       if ((ctrl & 0x80000000) && M1) {
+               freq = ref * N1 / M1;
+               if ((ctrl & 0x40000100) == 0x40000000) {
+                       if (M2)
+                               freq = freq * N2 / M2;
+                       else
+                               freq = 0;
+               }
+       }
+
+       return freq;
+}
+
+static int
+nv50_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct nv50_clk_priv *priv = (void *)clk;
+       u32 mast = nv_rd32(priv, 0x00c040);
+       u32 P = 0;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_href:
+               return 100000; /* PCIE reference clock */
+       case nv_clk_src_hclk:
+               return div_u64((u64)clk->read(clk, nv_clk_src_href) * 27778, 10000);
+       case nv_clk_src_hclkm3:
+               return clk->read(clk, nv_clk_src_hclk) * 3;
+       case nv_clk_src_hclkm3d2:
+               return clk->read(clk, nv_clk_src_hclk) * 3 / 2;
+       case nv_clk_src_host:
+               switch (mast & 0x30000000) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_href);
+               case 0x10000000: break;
+               case 0x20000000: /* !0x50 */
+               case 0x30000000: return clk->read(clk, nv_clk_src_hclk);
+               }
+               break;
+       case nv_clk_src_core:
+               if (!(mast & 0x00100000))
+                       P = (nv_rd32(priv, 0x004028) & 0x00070000) >> 16;
+               switch (mast & 0x00000003) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000001: return clk->read(clk, nv_clk_src_dom6);
+               case 0x00000002: return read_pll(priv, 0x004020) >> P;
+               case 0x00000003: return read_pll(priv, 0x004028) >> P;
+               }
+               break;
+       case nv_clk_src_shader:
+               P = (nv_rd32(priv, 0x004020) & 0x00070000) >> 16;
+               switch (mast & 0x00000030) {
+               case 0x00000000:
+                       if (mast & 0x00000080)
+                               return clk->read(clk, nv_clk_src_host) >> P;
+                       return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000010: break;
+               case 0x00000020: return read_pll(priv, 0x004028) >> P;
+               case 0x00000030: return read_pll(priv, 0x004020) >> P;
+               }
+               break;
+       case nv_clk_src_mem:
+               P = (nv_rd32(priv, 0x004008) & 0x00070000) >> 16;
+               if (nv_rd32(priv, 0x004008) & 0x00000200) {
+                       switch (mast & 0x0000c000) {
+                       case 0x00000000:
+                               return clk->read(clk, nv_clk_src_crystal) >> P;
+                       case 0x00008000:
+                       case 0x0000c000:
+                               return clk->read(clk, nv_clk_src_href) >> P;
+                       }
+               } else {
+                       return read_pll(priv, 0x004008) >> P;
+               }
+               break;
+       case nv_clk_src_vdec:
+               P = (read_div(priv) & 0x00000700) >> 8;
+               switch (nv_device(priv)->chipset) {
+               case 0x84:
+               case 0x86:
+               case 0x92:
+               case 0x94:
+               case 0x96:
+               case 0xa0:
+                       switch (mast & 0x00000c00) {
+                       case 0x00000000:
+                               if (nv_device(priv)->chipset == 0xa0) /* wtf?? */
+                                       return clk->read(clk, nv_clk_src_core) >> P;
+                               return clk->read(clk, nv_clk_src_crystal) >> P;
+                       case 0x00000400:
+                               return 0;
+                       case 0x00000800:
+                               if (mast & 0x01000000)
+                                       return read_pll(priv, 0x004028) >> P;
+                               return read_pll(priv, 0x004030) >> P;
+                       case 0x00000c00:
+                               return clk->read(clk, nv_clk_src_core) >> P;
+                       }
+                       break;
+               case 0x98:
+                       switch (mast & 0x00000c00) {
+                       case 0x00000000:
+                               return clk->read(clk, nv_clk_src_core) >> P;
+                       case 0x00000400:
+                               return 0;
+                       case 0x00000800:
+                               return clk->read(clk, nv_clk_src_hclkm3d2) >> P;
+                       case 0x00000c00:
+                               return clk->read(clk, nv_clk_src_mem) >> P;
+                       }
+                       break;
+               }
+               break;
+       case nv_clk_src_dom6:
+               switch (nv_device(priv)->chipset) {
+               case 0x50:
+               case 0xa0:
+                       return read_pll(priv, 0x00e810) >> 2;
+               case 0x84:
+               case 0x86:
+               case 0x92:
+               case 0x94:
+               case 0x96:
+               case 0x98:
+                       P = (read_div(priv) & 0x00000007) >> 0;
+                       switch (mast & 0x0c000000) {
+                       case 0x00000000: return clk->read(clk, nv_clk_src_href);
+                       case 0x04000000: break;
+                       case 0x08000000: return clk->read(clk, nv_clk_src_hclk);
+                       case 0x0c000000:
+                               return clk->read(clk, nv_clk_src_hclkm3) >> P;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       default:
+               break;
+       }
+
+       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
+       return -EINVAL;
+}
+
+static u32
+calc_pll(struct nv50_clk_priv *priv, u32 reg, u32 clk, int *N, int *M, int *P)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll pll;
+       int ret;
+
+       ret = nvbios_pll_parse(bios, reg, &pll);
+       if (ret)
+               return 0;
+
+       pll.vco2.max_freq = 0;
+       pll.refclk = read_pll_ref(priv, reg);
+       if (!pll.refclk)
+               return 0;
+
+       return nv04_pll_calc(nv_subdev(priv), &pll, clk, N, M, NULL, NULL, P);
+}
+
+static inline u32
+calc_div(u32 src, u32 target, int *div)
+{
+       u32 clk0 = src, clk1 = src;
+       for (*div = 0; *div <= 7; (*div)++) {
+               if (clk0 <= target) {
+                       clk1 = clk0 << (*div ? 1 : 0);
+                       break;
+               }
+               clk0 >>= 1;
+       }
+
+       if (target - clk0 <= clk1 - target)
+               return clk0;
+       (*div)--;
+       return clk1;
+}
+
+static inline u32
+clk_same(u32 a, u32 b)
+{
+       return ((a / 1000) == (b / 1000));
+}
+
+static int
+nv50_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct nv50_clk_priv *priv = (void *)clk;
+       struct nv50_clk_hwsq *hwsq = &priv->hwsq;
+       const int shader = cstate->domain[nv_clk_src_shader];
+       const int core = cstate->domain[nv_clk_src_core];
+       const int vdec = cstate->domain[nv_clk_src_vdec];
+       const int dom6 = cstate->domain[nv_clk_src_dom6];
+       u32 mastm = 0, mastv = 0;
+       u32 divsm = 0, divsv = 0;
+       int N, M, P1, P2;
+       int freq, out;
+
+       /* prepare a hwsq script from which we'll perform the reclock */
+       out = clk_init(hwsq, nv_subdev(clk));
+       if (out)
+               return out;
+
+       clk_wr32(hwsq, fifo, 0x00000001); /* block fifo */
+       clk_nsec(hwsq, 8000);
+       clk_setf(hwsq, 0x10, 0x00); /* disable fb */
+       clk_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */
+
+       /* vdec: avoid modifying xpll until we know exactly how the other
+        * clock domains work, i suspect at least some of them can also be
+        * tied to xpll...
+        */
+       if (vdec) {
+               /* see how close we can get using nvclk as a source */
+               freq = calc_div(core, vdec, &P1);
+
+               /* see how close we can get using xpll/hclk as a source */
+               if (nv_device(priv)->chipset != 0x98)
+                       out = read_pll(priv, 0x004030);
+               else
+                       out = clk->read(clk, nv_clk_src_hclkm3d2);
+               out = calc_div(out, vdec, &P2);
+
+               /* select whichever gets us closest */
+               if (abs(vdec - freq) <= abs(vdec - out)) {
+                       if (nv_device(priv)->chipset != 0x98)
+                               mastv |= 0x00000c00;
+                       divsv |= P1 << 8;
+               } else {
+                       mastv |= 0x00000800;
+                       divsv |= P2 << 8;
+               }
+
+               mastm |= 0x00000c00;
+               divsm |= 0x00000700;
+       }
+
+       /* dom6: nfi what this is, but we're limited to various combinations
+        * of the host clock frequency
+        */
+       if (dom6) {
+               if (clk_same(dom6, clk->read(clk, nv_clk_src_href))) {
+                       mastv |= 0x00000000;
+               } else
+               if (clk_same(dom6, clk->read(clk, nv_clk_src_hclk))) {
+                       mastv |= 0x08000000;
+               } else {
+                       freq = clk->read(clk, nv_clk_src_hclk) * 3;
+                       freq = calc_div(freq, dom6, &P1);
+
+                       mastv |= 0x0c000000;
+                       divsv |= P1;
+               }
+
+               mastm |= 0x0c000000;
+               divsm |= 0x00000007;
+       }
+
+       /* vdec/dom6: switch to "safe" clocks temporarily, update dividers
+        * and then switch to target clocks
+        */
+       clk_mask(hwsq, mast, mastm, 0x00000000);
+       clk_mask(hwsq, divs, divsm, divsv);
+       clk_mask(hwsq, mast, mastm, mastv);
+
+       /* core/shader: disconnect nvclk/sclk from their PLLs (nvclk to dom6,
+        * sclk to hclk) before reprogramming
+        */
+       if (nv_device(priv)->chipset < 0x92)
+               clk_mask(hwsq, mast, 0x001000b0, 0x00100080);
+       else
+               clk_mask(hwsq, mast, 0x000000b3, 0x00000081);
+
+       /* core: for the moment at least, always use nvpll */
+       freq = calc_pll(priv, 0x4028, core, &N, &M, &P1);
+       if (freq == 0)
+               return -ERANGE;
+
+       clk_mask(hwsq, nvpll[0], 0xc03f0100,
+                                0x80000000 | (P1 << 19) | (P1 << 16));
+       clk_mask(hwsq, nvpll[1], 0x0000ffff, (N << 8) | M);
+
+       /* shader: tie to nvclk if possible, otherwise use spll.  have to be
+        * very careful that the shader clock is at least twice the core, or
+        * some chipsets will be very unhappy.  i expect most or all of these
+        * cases will be handled by tying to nvclk, but it's possible there's
+        * corners
+        */
+       if (P1-- && shader == (core << 1)) {
+               clk_mask(hwsq, spll[0], 0xc03f0100, (P1 << 19) | (P1 << 16));
+               clk_mask(hwsq, mast, 0x00100033, 0x00000023);
+       } else {
+               freq = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
+               if (freq == 0)
+                       return -ERANGE;
+
+               clk_mask(hwsq, spll[0], 0xc03f0100,
+                                       0x80000000 | (P1 << 19) | (P1 << 16));
+               clk_mask(hwsq, spll[1], 0x0000ffff, (N << 8) | M);
+               clk_mask(hwsq, mast, 0x00100033, 0x00000033);
+       }
+
+       /* restore normal operation */
+       clk_setf(hwsq, 0x10, 0x01); /* enable fb */
+       clk_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */
+       clk_wr32(hwsq, fifo, 0x00000000); /* un-block fifo */
+       return 0;
+}
+
+static int
+nv50_clk_prog(struct nouveau_clk *clk)
+{
+       struct nv50_clk_priv *priv = (void *)clk;
+       return clk_exec(&priv->hwsq, true);
+}
+
+static void
+nv50_clk_tidy(struct nouveau_clk *clk)
+{
+       struct nv50_clk_priv *priv = (void *)clk;
+       clk_exec(&priv->hwsq, false);
+}
+
+int
+nv50_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nv50_clk_oclass *pclass = (void *)oclass;
+       struct nv50_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, pclass->domains,
+                                  NULL, 0, false, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->hwsq.r_fifo = hwsq_reg(0x002504);
+       priv->hwsq.r_spll[0] = hwsq_reg(0x004020);
+       priv->hwsq.r_spll[1] = hwsq_reg(0x004024);
+       priv->hwsq.r_nvpll[0] = hwsq_reg(0x004028);
+       priv->hwsq.r_nvpll[1] = hwsq_reg(0x00402c);
+       switch (nv_device(priv)->chipset) {
+       case 0x92:
+       case 0x94:
+       case 0x96:
+               priv->hwsq.r_divs = hwsq_reg(0x004800);
+               break;
+       default:
+               priv->hwsq.r_divs = hwsq_reg(0x004700);
+               break;
+       }
+       priv->hwsq.r_mast = hwsq_reg(0x00c040);
+
+       priv->base.read = nv50_clk_read;
+       priv->base.calc = nv50_clk_calc;
+       priv->base.prog = nv50_clk_prog;
+       priv->base.tidy = nv50_clk_tidy;
+       return 0;
+}
+
+static struct nouveau_domain
+nv50_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
+       { nv_clk_src_max }
+};
+
+struct nouveau_oclass *
+nv50_clk_oclass = &(struct nv50_clk_oclass) {
+       .base.handle = NV_SUBDEV(CLK, 0x50),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+       .domains = nv50_domains,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.h
new file mode 100644 (file)
index 0000000..ae6421f
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __NVKM_CLK_NV50_H__
+#define __NVKM_CLK_NV50_H__
+
+#include <subdev/bus.h>
+#include <subdev/bus/hwsq.h>
+#include <subdev/clk.h>
+
+struct nv50_clk_hwsq {
+       struct hwsq base;
+       struct hwsq_reg r_fifo;
+       struct hwsq_reg r_spll[2];
+       struct hwsq_reg r_nvpll[2];
+       struct hwsq_reg r_divs;
+       struct hwsq_reg r_mast;
+};
+
+struct nv50_clk_priv {
+       struct nouveau_clk base;
+       struct nv50_clk_hwsq hwsq;
+};
+
+int  nv50_clk_ctor(struct nouveau_object *, struct nouveau_object *,
+                    struct nouveau_oclass *, void *, u32,
+                    struct nouveau_object **);
+
+struct nv50_clk_oclass {
+       struct nouveau_oclass base;
+       struct nouveau_domain *domains;
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv84.c
new file mode 100644 (file)
index 0000000..b5b00b3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nv50.h"
+
+static struct nouveau_domain
+nv84_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
+       { nv_clk_src_vdec   , 0xff },
+       { nv_clk_src_max }
+};
+
+struct nouveau_oclass *
+nv84_clk_oclass = &(struct nv50_clk_oclass) {
+       .base.handle = NV_SUBDEV(CLK, 0x84),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+       .domains = nv84_domains,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nva3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nva3.c
new file mode 100644 (file)
index 0000000..3002c60
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ *          Roy Spliet
+ */
+
+#include <engine/fifo.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/timer.h>
+
+#include "pll.h"
+
+#include "nva3.h"
+
+struct nva3_clk_priv {
+       struct nouveau_clk base;
+       struct nva3_clk_info eng[nv_clk_src_max];
+};
+
+static u32 read_clk(struct nva3_clk_priv *, int, bool);
+static u32 read_pll(struct nva3_clk_priv *, int, u32);
+
+static u32
+read_vco(struct nva3_clk_priv *priv, int clk)
+{
+       u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4));
+
+       switch (sctl & 0x00000030) {
+       case 0x00000000:
+               return nv_device(priv)->crystal;
+       case 0x00000020:
+               return read_pll(priv, 0x41, 0x00e820);
+       case 0x00000030:
+               return read_pll(priv, 0x42, 0x00e8a0);
+       default:
+               return 0;
+       }
+}
+
+static u32
+read_clk(struct nva3_clk_priv *priv, int clk, bool ignore_en)
+{
+       u32 sctl, sdiv, sclk;
+
+       /* refclk for the 0xe8xx plls is a fixed frequency */
+       if (clk >= 0x40) {
+               if (nv_device(priv)->chipset == 0xaf) {
+                       /* no joke.. seriously.. sigh.. */
+                       return nv_rd32(priv, 0x00471c) * 1000;
+               }
+
+               return nv_device(priv)->crystal;
+       }
+
+       sctl = nv_rd32(priv, 0x4120 + (clk * 4));
+       if (!ignore_en && !(sctl & 0x00000100))
+               return 0;
+
+       /* out_alt */
+       if (sctl & 0x00000400)
+               return 108000;
+
+       /* vco_out */
+       switch (sctl & 0x00003000) {
+       case 0x00000000:
+               if (!(sctl & 0x00000200))
+                       return nv_device(priv)->crystal;
+               return 0;
+       case 0x00002000:
+               if (sctl & 0x00000040)
+                       return 108000;
+               return 100000;
+       case 0x00003000:
+               /* vco_enable */
+               if (!(sctl & 0x00000001))
+                       return 0;
+
+               sclk = read_vco(priv, clk);
+               sdiv = ((sctl & 0x003f0000) >> 16) + 2;
+               return (sclk * 2) / sdiv;
+       default:
+               return 0;
+       }
+}
+
+static u32
+read_pll(struct nva3_clk_priv *priv, int clk, u32 pll)
+{
+       u32 ctrl = nv_rd32(priv, pll + 0);
+       u32 sclk = 0, P = 1, N = 1, M = 1;
+
+       if (!(ctrl & 0x00000008)) {
+               if (ctrl & 0x00000001) {
+                       u32 coef = nv_rd32(priv, pll + 4);
+                       M = (coef & 0x000000ff) >> 0;
+                       N = (coef & 0x0000ff00) >> 8;
+                       P = (coef & 0x003f0000) >> 16;
+
+                       /* no post-divider on these..
+                        * XXX: it looks more like two post-"dividers" that
+                        * cross each other out in the default RPLL config */
+                       if ((pll & 0x00ff00) == 0x00e800)
+                               P = 1;
+
+                       sclk = read_clk(priv, 0x00 + clk, false);
+               }
+       } else {
+               sclk = read_clk(priv, 0x10 + clk, false);
+       }
+
+       if (M * P)
+               return sclk * N / (M * P);
+       return 0;
+}
+
+static int
+nva3_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct nva3_clk_priv *priv = (void *)clk;
+       u32 hsrc;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_core:
+       case nv_clk_src_core_intm:
+               return read_pll(priv, 0x00, 0x4200);
+       case nv_clk_src_shader:
+               return read_pll(priv, 0x01, 0x4220);
+       case nv_clk_src_mem:
+               return read_pll(priv, 0x02, 0x4000);
+       case nv_clk_src_disp:
+               return read_clk(priv, 0x20, false);
+       case nv_clk_src_vdec:
+               return read_clk(priv, 0x21, false);
+       case nv_clk_src_daemon:
+               return read_clk(priv, 0x25, false);
+       case nv_clk_src_host:
+               hsrc = (nv_rd32(priv, 0xc040) & 0x30000000) >> 28;
+               switch (hsrc) {
+               case 0:
+                       return read_clk(priv, 0x1d, false);
+               case 2:
+               case 3:
+                       return 277000;
+               default:
+                       nv_error(clk, "unknown HOST clock source %d\n", hsrc);
+                       return -EINVAL;
+               }
+       default:
+               nv_error(clk, "invalid clock source %d\n", src);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int
+nva3_clk_info(struct nouveau_clk *clock, int clk, u32 khz,
+               struct nva3_clk_info *info)
+{
+       struct nva3_clk_priv *priv = (void *)clock;
+       u32 oclk, sclk, sdiv, diff;
+
+       info->clk = 0;
+
+       switch (khz) {
+       case 27000:
+               info->clk = 0x00000100;
+               return khz;
+       case 100000:
+               info->clk = 0x00002100;
+               return khz;
+       case 108000:
+               info->clk = 0x00002140;
+               return khz;
+       default:
+               sclk = read_vco(priv, clk);
+               sdiv = min((sclk * 2) / khz, (u32)65);
+               oclk = (sclk * 2) / sdiv;
+               diff = ((khz + 3000) - oclk);
+
+               /* When imprecise, play it safe and aim for a clock lower than
+                * desired rather than higher */
+               if (diff < 0) {
+                       sdiv++;
+                       oclk = (sclk * 2) / sdiv;
+               }
+
+               /* divider can go as low as 2, limited here because NVIDIA
+                * and the VBIOS on my NVA8 seem to prefer using the PLL
+                * for 810MHz - is there a good reason?
+                * XXX: PLLs with refclk 810MHz?  */
+               if (sdiv > 4) {
+                       info->clk = (((sdiv - 2) << 16) | 0x00003100);
+                       return oclk;
+               }
+
+               break;
+       }
+
+       return -ERANGE;
+}
+
+int
+nva3_pll_info(struct nouveau_clk *clock, int clk, u32 pll, u32 khz,
+               struct nva3_clk_info *info)
+{
+       struct nouveau_bios *bios = nouveau_bios(clock);
+       struct nva3_clk_priv *priv = (void *)clock;
+       struct nvbios_pll limits;
+       int P, N, M, diff;
+       int ret;
+
+       info->pll = 0;
+
+       /* If we can get a within [-2, 3) MHz of a divider, we'll disable the
+        * PLL and use the divider instead. */
+       ret = nva3_clk_info(clock, clk, khz, info);
+       diff = khz - ret;
+       if (!pll || (diff >= -2000 && diff < 3000)) {
+               goto out;
+       }
+
+       /* Try with PLL */
+       ret = nvbios_pll_parse(bios, pll, &limits);
+       if (ret)
+               return ret;
+
+       ret = nva3_clk_info(clock, clk - 0x10, limits.refclk, info);
+       if (ret != limits.refclk)
+               return -EINVAL;
+
+       ret = nva3_pll_calc(nv_subdev(priv), &limits, khz, &N, NULL, &M, &P);
+       if (ret >= 0) {
+               info->pll = (P << 16) | (N << 8) | M;
+       }
+
+out:
+       info->fb_delay = max(((khz + 7566) / 15133), (u32) 18);
+
+       return ret ? ret : -ERANGE;
+}
+
+static int
+calc_clk(struct nva3_clk_priv *priv, struct nouveau_cstate *cstate,
+        int clk, u32 pll, int idx)
+{
+       int ret = nva3_pll_info(&priv->base, clk, pll, cstate->domain[idx],
+                                 &priv->eng[idx]);
+       if (ret >= 0)
+               return 0;
+       return ret;
+}
+
+static int
+calc_host(struct nva3_clk_priv *priv, struct nouveau_cstate *cstate)
+{
+       int ret = 0;
+       u32 kHz = cstate->domain[nv_clk_src_host];
+       struct nva3_clk_info *info = &priv->eng[nv_clk_src_host];
+
+       if (kHz == 277000) {
+               info->clk = 0;
+               info->host_out = NVA3_HOST_277;
+               return 0;
+       }
+
+       info->host_out = NVA3_HOST_CLK;
+
+       ret = nva3_clk_info(&priv->base, 0x1d, kHz, info);
+       if (ret >= 0)
+               return 0;
+       return ret;
+}
+
+int
+nva3_clk_pre(struct nouveau_clk *clk, unsigned long *flags)
+{
+       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+
+       /* halt and idle execution engines */
+       nv_mask(clk, 0x020060, 0x00070000, 0x00000000);
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000001);
+       /* Wait until the interrupt handler is finished */
+       if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000))
+               return -EBUSY;
+
+       if (pfifo)
+               pfifo->pause(pfifo, flags);
+
+       if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010))
+               return -EIO;
+       if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f))
+               return -EIO;
+
+       return 0;
+}
+
+void
+nva3_clk_post(struct nouveau_clk *clk, unsigned long *flags)
+{
+       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+
+       if (pfifo && flags)
+               pfifo->start(pfifo, flags);
+
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000000);
+       nv_mask(clk, 0x020060, 0x00070000, 0x00040000);
+}
+
+static void
+disable_clk_src(struct nva3_clk_priv *priv, u32 src)
+{
+       nv_mask(priv, src, 0x00000100, 0x00000000);
+       nv_mask(priv, src, 0x00000001, 0x00000000);
+}
+
+static void
+prog_pll(struct nva3_clk_priv *priv, int clk, u32 pll, int idx)
+{
+       struct nva3_clk_info *info = &priv->eng[idx];
+       const u32 src0 = 0x004120 + (clk * 4);
+       const u32 src1 = 0x004160 + (clk * 4);
+       const u32 ctrl = pll + 0;
+       const u32 coef = pll + 4;
+       u32 bypass;
+
+       if (info->pll) {
+               /* Always start from a non-PLL clock */
+               bypass = nv_rd32(priv, ctrl)  & 0x00000008;
+               if (!bypass) {
+                       nv_mask(priv, src1, 0x00000101, 0x00000101);
+                       nv_mask(priv, ctrl, 0x00000008, 0x00000008);
+                       udelay(20);
+               }
+
+               nv_mask(priv, src0, 0x003f3141, 0x00000101 | info->clk);
+               nv_wr32(priv, coef, info->pll);
+               nv_mask(priv, ctrl, 0x00000015, 0x00000015);
+               nv_mask(priv, ctrl, 0x00000010, 0x00000000);
+               if (!nv_wait(priv, ctrl, 0x00020000, 0x00020000)) {
+                       nv_mask(priv, ctrl, 0x00000010, 0x00000010);
+                       nv_mask(priv, src0, 0x00000101, 0x00000000);
+                       return;
+               }
+               nv_mask(priv, ctrl, 0x00000010, 0x00000010);
+               nv_mask(priv, ctrl, 0x00000008, 0x00000000);
+               disable_clk_src(priv, src1);
+       } else {
+               nv_mask(priv, src1, 0x003f3141, 0x00000101 | info->clk);
+               nv_mask(priv, ctrl, 0x00000018, 0x00000018);
+               udelay(20);
+               nv_mask(priv, ctrl, 0x00000001, 0x00000000);
+               disable_clk_src(priv, src0);
+       }
+}
+
+static void
+prog_clk(struct nva3_clk_priv *priv, int clk, int idx)
+{
+       struct nva3_clk_info *info = &priv->eng[idx];
+       nv_mask(priv, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | info->clk);
+}
+
+static void
+prog_host(struct nva3_clk_priv *priv)
+{
+       struct nva3_clk_info *info = &priv->eng[nv_clk_src_host];
+       u32 hsrc = (nv_rd32(priv, 0xc040));
+
+       switch (info->host_out) {
+       case NVA3_HOST_277:
+               if ((hsrc & 0x30000000) == 0) {
+                       nv_wr32(priv, 0xc040, hsrc | 0x20000000);
+                       disable_clk_src(priv, 0x4194);
+               }
+               break;
+       case NVA3_HOST_CLK:
+               prog_clk(priv, 0x1d, nv_clk_src_host);
+               if ((hsrc & 0x30000000) >= 0x20000000) {
+                       nv_wr32(priv, 0xc040, hsrc & ~0x30000000);
+               }
+               break;
+       default:
+               break;
+       }
+
+       /* This seems to be a clock gating factor on idle, always set to 64 */
+       nv_wr32(priv, 0xc044, 0x3e);
+}
+
+static void
+prog_core(struct nva3_clk_priv *priv, int idx)
+{
+       struct nva3_clk_info *info = &priv->eng[idx];
+       u32 fb_delay = nv_rd32(priv, 0x10002c);
+
+       if (fb_delay < info->fb_delay)
+               nv_wr32(priv, 0x10002c, info->fb_delay);
+
+       prog_pll(priv, 0x00, 0x004200, idx);
+
+       if (fb_delay > info->fb_delay)
+               nv_wr32(priv, 0x10002c, info->fb_delay);
+}
+
+static int
+nva3_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct nva3_clk_priv *priv = (void *)clk;
+       struct nva3_clk_info *core = &priv->eng[nv_clk_src_core];
+       int ret;
+
+       if ((ret = calc_clk(priv, cstate, 0x10, 0x4200, nv_clk_src_core)) ||
+           (ret = calc_clk(priv, cstate, 0x11, 0x4220, nv_clk_src_shader)) ||
+           (ret = calc_clk(priv, cstate, 0x20, 0x0000, nv_clk_src_disp)) ||
+           (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec)) ||
+           (ret = calc_host(priv, cstate)))
+               return ret;
+
+       /* XXX: Should be reading the highest bit in the VBIOS clock to decide
+        * whether to use a PLL or not... but using a PLL defeats the purpose */
+       if (core->pll) {
+               ret = nva3_clk_info(clk, 0x10,
+                               cstate->domain[nv_clk_src_core_intm],
+                               &priv->eng[nv_clk_src_core_intm]);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+nva3_clk_prog(struct nouveau_clk *clk)
+{
+       struct nva3_clk_priv *priv = (void *)clk;
+       struct nva3_clk_info *core = &priv->eng[nv_clk_src_core];
+       int ret = 0;
+       unsigned long flags;
+       unsigned long *f = &flags;
+
+       ret = nva3_clk_pre(clk, f);
+       if (ret)
+               goto out;
+
+       if (core->pll)
+               prog_core(priv, nv_clk_src_core_intm);
+
+       prog_core(priv,  nv_clk_src_core);
+       prog_pll(priv, 0x01, 0x004220, nv_clk_src_shader);
+       prog_clk(priv, 0x20, nv_clk_src_disp);
+       prog_clk(priv, 0x21, nv_clk_src_vdec);
+       prog_host(priv);
+
+out:
+       if (ret == -EBUSY)
+               f = NULL;
+
+       nva3_clk_post(clk, f);
+
+       return ret;
+}
+
+static void
+nva3_clk_tidy(struct nouveau_clk *clk)
+{
+}
+
+static struct nouveau_domain
+nva3_domain[] = {
+       { nv_clk_src_crystal  , 0xff },
+       { nv_clk_src_core     , 0x00, 0, "core", 1000 },
+       { nv_clk_src_shader   , 0x01, 0, "shader", 1000 },
+       { nv_clk_src_mem      , 0x02, 0, "memory", 1000 },
+       { nv_clk_src_vdec     , 0x03 },
+       { nv_clk_src_disp     , 0x04 },
+       { nv_clk_src_host     , 0x05 },
+       { nv_clk_src_core_intm, 0x06 },
+       { nv_clk_src_max }
+};
+
+static int
+nva3_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nva3_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, nva3_domain, NULL, 0,
+                                  true, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nva3_clk_read;
+       priv->base.calc = nva3_clk_calc;
+       priv->base.prog = nva3_clk_prog;
+       priv->base.tidy = nva3_clk_tidy;
+       return 0;
+}
+
+struct nouveau_oclass
+nva3_clk_oclass = {
+       .handle = NV_SUBDEV(CLK, 0xa3),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nva3_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nva3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nva3.h
new file mode 100644 (file)
index 0000000..ce0fc83
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __NVKM_CLK_NVA3_H__
+#define __NVKM_CLK_NVA3_H__
+
+#include <subdev/clk.h>
+
+struct nva3_clk_info {
+       u32 clk;
+       u32 pll;
+       enum {
+               NVA3_HOST_277,
+               NVA3_HOST_CLK,
+       } host_out;
+       u32 fb_delay;
+};
+
+int nva3_pll_info(struct nouveau_clk *, int, u32, u32,
+                   struct nva3_clk_info *);
+int nva3_clk_pre(struct nouveau_clk *clk, unsigned long *flags);
+void nva3_clk_post(struct nouveau_clk *clk, unsigned long *flags);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nvaa.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nvaa.c
new file mode 100644 (file)
index 0000000..d6d2bd1
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/fifo.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/timer.h>
+#include <subdev/clk.h>
+
+#include "nva3.h"
+#include "pll.h"
+
+struct nvaa_clk_priv {
+       struct nouveau_clk base;
+       enum nv_clk_src csrc, ssrc, vsrc;
+       u32 cctrl, sctrl;
+       u32 ccoef, scoef;
+       u32 cpost, spost;
+       u32 vdiv;
+};
+
+static u32
+read_div(struct nouveau_clk *clk)
+{
+       return nv_rd32(clk, 0x004600);
+}
+
+static u32
+read_pll(struct nouveau_clk *clk, u32 base)
+{
+       u32 ctrl = nv_rd32(clk, base + 0);
+       u32 coef = nv_rd32(clk, base + 4);
+       u32 ref = clk->read(clk, nv_clk_src_href);
+       u32 post_div = 0;
+       u32 clock = 0;
+       int N1, M1;
+
+       switch (base){
+       case 0x4020:
+               post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16);
+               break;
+       case 0x4028:
+               post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16;
+               break;
+       default:
+               break;
+       }
+
+       N1 = (coef & 0x0000ff00) >> 8;
+       M1 = (coef & 0x000000ff);
+       if ((ctrl & 0x80000000) && M1) {
+               clock = ref * N1 / M1;
+               clock = clock / post_div;
+       }
+
+       return clock;
+}
+
+static int
+nvaa_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct nvaa_clk_priv *priv = (void *)clk;
+       u32 mast = nv_rd32(clk, 0x00c054);
+       u32 P = 0;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_href:
+               return 100000; /* PCIE reference clock */
+       case nv_clk_src_hclkm4:
+               return clk->read(clk, nv_clk_src_href) * 4;
+       case nv_clk_src_hclkm2d3:
+               return clk->read(clk, nv_clk_src_href) * 2 / 3;
+       case nv_clk_src_host:
+               switch (mast & 0x000c0000) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3);
+               case 0x00040000: break;
+               case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x000c0000: return clk->read(clk, nv_clk_src_cclk);
+               }
+               break;
+       case nv_clk_src_core:
+               P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16;
+
+               switch (mast & 0x00000003) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000001: return 0;
+               case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P;
+               case 0x00000003: return read_pll(clk, 0x004028) >> P;
+               }
+               break;
+       case nv_clk_src_cclk:
+               if ((mast & 0x03000000) != 0x03000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               if ((mast & 0x00000200) == 0x00000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               switch (mast & 0x00000c00) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_href);
+               case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3);
+               default: return 0;
+               }
+       case nv_clk_src_shader:
+               P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16;
+               switch (mast & 0x00000030) {
+               case 0x00000000:
+                       if (mast & 0x00000040)
+                               return clk->read(clk, nv_clk_src_href) >> P;
+                       return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000010: break;
+               case 0x00000020: return read_pll(clk, 0x004028) >> P;
+               case 0x00000030: return read_pll(clk, 0x004020) >> P;
+               }
+               break;
+       case nv_clk_src_mem:
+               return 0;
+               break;
+       case nv_clk_src_vdec:
+               P = (read_div(clk) & 0x00000700) >> 8;
+
+               switch (mast & 0x00400000) {
+               case 0x00400000:
+                       return clk->read(clk, nv_clk_src_core) >> P;
+                       break;
+               default:
+                       return 500000 >> P;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
+       return 0;
+}
+
+static u32
+calc_pll(struct nvaa_clk_priv *priv, u32 reg,
+        u32 clock, int *N, int *M, int *P)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll pll;
+       struct nouveau_clk *clk = &priv->base;
+       int ret;
+
+       ret = nvbios_pll_parse(bios, reg, &pll);
+       if (ret)
+               return 0;
+
+       pll.vco2.max_freq = 0;
+       pll.refclk = clk->read(clk, nv_clk_src_href);
+       if (!pll.refclk)
+               return 0;
+
+       return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P);
+}
+
+static inline u32
+calc_P(u32 src, u32 target, int *div)
+{
+       u32 clk0 = src, clk1 = src;
+       for (*div = 0; *div <= 7; (*div)++) {
+               if (clk0 <= target) {
+                       clk1 = clk0 << (*div ? 1 : 0);
+                       break;
+               }
+               clk0 >>= 1;
+       }
+
+       if (target - clk0 <= clk1 - target)
+               return clk0;
+       (*div)--;
+       return clk1;
+}
+
+static int
+nvaa_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct nvaa_clk_priv *priv = (void *)clk;
+       const int shader = cstate->domain[nv_clk_src_shader];
+       const int core = cstate->domain[nv_clk_src_core];
+       const int vdec = cstate->domain[nv_clk_src_vdec];
+       u32 out = 0, clock = 0;
+       int N, M, P1, P2 = 0;
+       int divs = 0;
+
+       /* cclk: find suitable source, disable PLL if we can */
+       if (core < clk->read(clk, nv_clk_src_hclkm4))
+               out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs);
+
+       /* Calculate clock * 2, so shader clock can use it too */
+       clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1);
+
+       if (abs(core - out) <=
+           abs(core - (clock >> 1))) {
+               priv->csrc = nv_clk_src_hclkm4;
+               priv->cctrl = divs << 16;
+       } else {
+               /* NVCTRL is actually used _after_ NVPOST, and after what we
+                * call NVPLL. To make matters worse, NVPOST is an integer
+                * divider instead of a right-shift number. */
+               if(P1 > 2) {
+                       P2 = P1 - 2;
+                       P1 = 2;
+               }
+
+               priv->csrc = nv_clk_src_core;
+               priv->ccoef = (N << 8) | M;
+
+               priv->cctrl = (P2 + 1) << 16;
+               priv->cpost = (1 << P1) << 16;
+       }
+
+       /* sclk: nvpll + divisor, href or spll */
+       out = 0;
+       if (shader == clk->read(clk, nv_clk_src_href)) {
+               priv->ssrc = nv_clk_src_href;
+       } else {
+               clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
+               if (priv->csrc == nv_clk_src_core) {
+                       out = calc_P((core << 1), shader, &divs);
+               }
+
+               if (abs(shader - out) <=
+                   abs(shader - clock) &&
+                  (divs + P2) <= 7) {
+                       priv->ssrc = nv_clk_src_core;
+                       priv->sctrl = (divs + P2) << 16;
+               } else {
+                       priv->ssrc = nv_clk_src_shader;
+                       priv->scoef = (N << 8) | M;
+                       priv->sctrl = P1 << 16;
+               }
+       }
+
+       /* vclk */
+       out = calc_P(core, vdec, &divs);
+       clock = calc_P(500000, vdec, &P1);
+       if(abs(vdec - out) <=
+          abs(vdec - clock)) {
+               priv->vsrc = nv_clk_src_cclk;
+               priv->vdiv = divs << 16;
+       } else {
+               priv->vsrc = nv_clk_src_vdec;
+               priv->vdiv = P1 << 16;
+       }
+
+       /* Print strategy! */
+       nv_debug(priv, "nvpll: %08x %08x %08x\n",
+                       priv->ccoef, priv->cpost, priv->cctrl);
+       nv_debug(priv, " spll: %08x %08x %08x\n",
+                       priv->scoef, priv->spost, priv->sctrl);
+       nv_debug(priv, " vdiv: %08x\n", priv->vdiv);
+       if (priv->csrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "core: hrefm4\n");
+       else
+               nv_debug(priv, "core: nvpll\n");
+
+       if (priv->ssrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "shader: hrefm4\n");
+       else if (priv->ssrc == nv_clk_src_core)
+               nv_debug(priv, "shader: nvpll\n");
+       else
+               nv_debug(priv, "shader: spll\n");
+
+       if (priv->vsrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "vdec: 500MHz\n");
+       else
+               nv_debug(priv, "vdec: core\n");
+
+       return 0;
+}
+
+static int
+nvaa_clk_prog(struct nouveau_clk *clk)
+{
+       struct nvaa_clk_priv *priv = (void *)clk;
+       u32 pllmask = 0, mast;
+       unsigned long flags;
+       unsigned long *f = &flags;
+       int ret = 0;
+
+       ret = nva3_clk_pre(clk, f);
+       if (ret)
+               goto out;
+
+       /* First switch to safe clocks: href */
+       mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640);
+       mast &= ~0x00400e73;
+       mast |= 0x03000000;
+
+       switch (priv->csrc) {
+       case nv_clk_src_hclkm4:
+               nv_mask(clk, 0x4028, 0x00070000, priv->cctrl);
+               mast |= 0x00000002;
+               break;
+       case nv_clk_src_core:
+               nv_wr32(clk, 0x402c, priv->ccoef);
+               nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl);
+               nv_wr32(clk, 0x4040, priv->cpost);
+               pllmask |= (0x3 << 8);
+               mast |= 0x00000003;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown core clock\n");
+               goto resume;
+       }
+
+       switch (priv->ssrc) {
+       case nv_clk_src_href:
+               nv_mask(clk, 0x4020, 0x00070000, 0x00000000);
+               /* mast |= 0x00000000; */
+               break;
+       case nv_clk_src_core:
+               nv_mask(clk, 0x4020, 0x00070000, priv->sctrl);
+               mast |= 0x00000020;
+               break;
+       case nv_clk_src_shader:
+               nv_wr32(clk, 0x4024, priv->scoef);
+               nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl);
+               nv_wr32(clk, 0x4070, priv->spost);
+               pllmask |= (0x3 << 12);
+               mast |= 0x00000030;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown sclk clock\n");
+               goto resume;
+       }
+
+       if (!nv_wait(clk, 0x004080, pllmask, pllmask)) {
+               nv_warn(priv,"Reclocking failed: unstable PLLs\n");
+               goto resume;
+       }
+
+       switch (priv->vsrc) {
+       case nv_clk_src_cclk:
+               mast |= 0x00400000;
+       default:
+               nv_wr32(clk, 0x4600, priv->vdiv);
+       }
+
+       nv_wr32(clk, 0xc054, mast);
+
+resume:
+       /* Disable some PLLs and dividers when unused */
+       if (priv->csrc != nv_clk_src_core) {
+               nv_wr32(clk, 0x4040, 0x00000000);
+               nv_mask(clk, 0x4028, 0x80000000, 0x00000000);
+       }
+
+       if (priv->ssrc != nv_clk_src_shader) {
+               nv_wr32(clk, 0x4070, 0x00000000);
+               nv_mask(clk, 0x4020, 0x80000000, 0x00000000);
+       }
+
+out:
+       if (ret == -EBUSY)
+               f = NULL;
+
+       nva3_clk_post(clk, f);
+
+       return ret;
+}
+
+static void
+nvaa_clk_tidy(struct nouveau_clk *clk)
+{
+}
+
+static struct nouveau_domain
+nvaa_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_vdec   , 0xff, 0, "vdec", 1000 },
+       { nv_clk_src_max }
+};
+
+static int
+nvaa_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nvaa_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, nvaa_domains, NULL,
+                                  0, true, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nvaa_clk_read;
+       priv->base.calc = nvaa_clk_calc;
+       priv->base.prog = nvaa_clk_prog;
+       priv->base.tidy = nvaa_clk_tidy;
+       return 0;
+}
+
+struct nouveau_oclass *
+nvaa_clk_oclass = &(struct nouveau_oclass) {
+       .handle = NV_SUBDEV(CLK, 0xaa),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvaa_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nvc0.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nvc0.c
new file mode 100644 (file)
index 0000000..791a9f5
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/clk.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/timer.h>
+
+#include "pll.h"
+
+struct nvc0_clk_info {
+       u32 freq;
+       u32 ssel;
+       u32 mdiv;
+       u32 dsrc;
+       u32 ddiv;
+       u32 coef;
+};
+
+struct nvc0_clk_priv {
+       struct nouveau_clk base;
+       struct nvc0_clk_info eng[16];
+};
+
+static u32 read_div(struct nvc0_clk_priv *, int, u32, u32);
+
+static u32
+read_vco(struct nvc0_clk_priv *priv, u32 dsrc)
+{
+       struct nouveau_clk *clk = &priv->base;
+       u32 ssrc = nv_rd32(priv, dsrc);
+       if (!(ssrc & 0x00000100))
+               return clk->read(clk, nv_clk_src_sppll0);
+       return clk->read(clk, nv_clk_src_sppll1);
+}
+
+static u32
+read_pll(struct nvc0_clk_priv *priv, u32 pll)
+{
+       struct nouveau_clk *clk = &priv->base;
+       u32 ctrl = nv_rd32(priv, pll + 0x00);
+       u32 coef = nv_rd32(priv, pll + 0x04);
+       u32 P = (coef & 0x003f0000) >> 16;
+       u32 N = (coef & 0x0000ff00) >> 8;
+       u32 M = (coef & 0x000000ff) >> 0;
+       u32 sclk;
+
+       if (!(ctrl & 0x00000001))
+               return 0;
+
+       switch (pll) {
+       case 0x00e800:
+       case 0x00e820:
+               sclk = nv_device(priv)->crystal;
+               P = 1;
+               break;
+       case 0x132000:
+               sclk = clk->read(clk, nv_clk_src_mpllsrc);
+               break;
+       case 0x132020:
+               sclk = clk->read(clk, nv_clk_src_mpllsrcref);
+               break;
+       case 0x137000:
+       case 0x137020:
+       case 0x137040:
+       case 0x1370e0:
+               sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140);
+               break;
+       default:
+               return 0;
+       }
+
+       return sclk * N / M / P;
+}
+
+static u32
+read_div(struct nvc0_clk_priv *priv, int doff, u32 dsrc, u32 dctl)
+{
+       u32 ssrc = nv_rd32(priv, dsrc + (doff * 4));
+       u32 sctl = nv_rd32(priv, dctl + (doff * 4));
+
+       switch (ssrc & 0x00000003) {
+       case 0:
+               if ((ssrc & 0x00030000) != 0x00030000)
+                       return nv_device(priv)->crystal;
+               return 108000;
+       case 2:
+               return 100000;
+       case 3:
+               if (sctl & 0x80000000) {
+                       u32 sclk = read_vco(priv, dsrc + (doff * 4));
+                       u32 sdiv = (sctl & 0x0000003f) + 2;
+                       return (sclk * 2) / sdiv;
+               }
+
+               return read_vco(priv, dsrc + (doff * 4));
+       default:
+               return 0;
+       }
+}
+
+static u32
+read_clk(struct nvc0_clk_priv *priv, int clk)
+{
+       u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4));
+       u32 ssel = nv_rd32(priv, 0x137100);
+       u32 sclk, sdiv;
+
+       if (ssel & (1 << clk)) {
+               if (clk < 7)
+                       sclk = read_pll(priv, 0x137000 + (clk * 0x20));
+               else
+                       sclk = read_pll(priv, 0x1370e0);
+               sdiv = ((sctl & 0x00003f00) >> 8) + 2;
+       } else {
+               sclk = read_div(priv, clk, 0x137160, 0x1371d0);
+               sdiv = ((sctl & 0x0000003f) >> 0) + 2;
+       }
+
+       if (sctl & 0x80000000)
+               return (sclk * 2) / sdiv;
+
+       return sclk;
+}
+
+static int
+nvc0_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct nouveau_device *device = nv_device(clk);
+       struct nvc0_clk_priv *priv = (void *)clk;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return device->crystal;
+       case nv_clk_src_href:
+               return 100000;
+       case nv_clk_src_sppll0:
+               return read_pll(priv, 0x00e800);
+       case nv_clk_src_sppll1:
+               return read_pll(priv, 0x00e820);
+
+       case nv_clk_src_mpllsrcref:
+               return read_div(priv, 0, 0x137320, 0x137330);
+       case nv_clk_src_mpllsrc:
+               return read_pll(priv, 0x132020);
+       case nv_clk_src_mpll:
+               return read_pll(priv, 0x132000);
+       case nv_clk_src_mdiv:
+               return read_div(priv, 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);
+
+       case nv_clk_src_gpc:
+               return read_clk(priv, 0x00);
+       case nv_clk_src_rop:
+               return read_clk(priv, 0x01);
+       case nv_clk_src_hubk07:
+               return read_clk(priv, 0x02);
+       case nv_clk_src_hubk06:
+               return read_clk(priv, 0x07);
+       case nv_clk_src_hubk01:
+               return read_clk(priv, 0x08);
+       case nv_clk_src_copy:
+               return read_clk(priv, 0x09);
+       case nv_clk_src_daemon:
+               return read_clk(priv, 0x0c);
+       case nv_clk_src_vdec:
+               return read_clk(priv, 0x0e);
+       default:
+               nv_error(clk, "invalid clock source %d\n", src);
+               return -EINVAL;
+       }
+}
+
+static u32
+calc_div(struct nvc0_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv)
+{
+       u32 div = min((ref * 2) / freq, (u32)65);
+       if (div < 2)
+               div = 2;
+
+       *ddiv = div - 2;
+       return (ref * 2) / div;
+}
+
+static u32
+calc_src(struct nvc0_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
+{
+       u32 sclk;
+
+       /* use one of the fixed frequencies if possible */
+       *ddiv = 0x00000000;
+       switch (freq) {
+       case  27000:
+       case 108000:
+               *dsrc = 0x00000000;
+               if (freq == 108000)
+                       *dsrc |= 0x00030000;
+               return freq;
+       case 100000:
+               *dsrc = 0x00000002;
+               return freq;
+       default:
+               *dsrc = 0x00000003;
+               break;
+       }
+
+       /* otherwise, calculate the closest divider */
+       sclk = read_vco(priv, 0x137160 + (clk * 4));
+       if (clk < 7)
+               sclk = calc_div(priv, clk, sclk, freq, ddiv);
+       return sclk;
+}
+
+static u32
+calc_pll(struct nvc0_clk_priv *priv, int clk, u32 freq, u32 *coef)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll limits;
+       int N, M, P, ret;
+
+       ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits);
+       if (ret)
+               return 0;
+
+       limits.refclk = read_div(priv, clk, 0x137120, 0x137140);
+       if (!limits.refclk)
+               return 0;
+
+       ret = nva3_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P);
+       if (ret <= 0)
+               return 0;
+
+       *coef = (P << 16) | (N << 8) | M;
+       return ret;
+}
+
+static int
+calc_clk(struct nvc0_clk_priv *priv,
+        struct nouveau_cstate *cstate, int clk, int dom)
+{
+       struct nvc0_clk_info *info = &priv->eng[clk];
+       u32 freq = cstate->domain[dom];
+       u32 src0, div0, div1D, div1P = 0;
+       u32 clk0, clk1 = 0;
+
+       /* invalid clock domain */
+       if (!freq)
+               return 0;
+
+       /* first possible path, using only dividers */
+       clk0 = calc_src(priv, clk, freq, &src0, &div0);
+       clk0 = calc_div(priv, clk, 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);
+               else
+                       clk1 = cstate->domain[nv_clk_src_hubk06];
+               clk1 = calc_div(priv, clk, clk1, freq, &div1P);
+       }
+
+       /* select the method which gets closest to target freq */
+       if (abs((int)freq - clk0) <= abs((int)freq - clk1)) {
+               info->dsrc = src0;
+               if (div0) {
+                       info->ddiv |= 0x80000000;
+                       info->ddiv |= div0 << 8;
+                       info->ddiv |= div0;
+               }
+               if (div1D) {
+                       info->mdiv |= 0x80000000;
+                       info->mdiv |= div1D;
+               }
+               info->ssel = info->coef = 0;
+               info->freq = clk0;
+       } else {
+               if (div1P) {
+                       info->mdiv |= 0x80000000;
+                       info->mdiv |= div1P << 8;
+               }
+               info->ssel = (1 << clk);
+               info->freq = clk1;
+       }
+
+       return 0;
+}
+
+static int
+nvc0_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct nvc0_clk_priv *priv = (void *)clk;
+       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)))
+               return ret;
+
+       return 0;
+}
+
+static void
+nvc0_clk_prog_0(struct nvc0_clk_priv *priv, int clk)
+{
+       struct nvc0_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);
+       }
+}
+
+static void
+nvc0_clk_prog_1(struct nvc0_clk_priv *priv, int clk)
+{
+       nv_mask(priv, 0x137100, (1 << clk), 0x00000000);
+       nv_wait(priv, 0x137100, (1 << clk), 0x00000000);
+}
+
+static void
+nvc0_clk_prog_2(struct nvc0_clk_priv *priv, int clk)
+{
+       struct nvc0_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);
+               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);
+               }
+       }
+}
+
+static void
+nvc0_clk_prog_3(struct nvc0_clk_priv *priv, int clk)
+{
+       struct nvc0_clk_info *info = &priv->eng[clk];
+       if (info->ssel) {
+               nv_mask(priv, 0x137100, (1 << clk), info->ssel);
+               nv_wait(priv, 0x137100, (1 << clk), info->ssel);
+       }
+}
+
+static void
+nvc0_clk_prog_4(struct nvc0_clk_priv *priv, int clk)
+{
+       struct nvc0_clk_info *info = &priv->eng[clk];
+       nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv);
+}
+
+static int
+nvc0_clk_prog(struct nouveau_clk *clk)
+{
+       struct nvc0_clk_priv *priv = (void *)clk;
+       struct {
+               void (*exec)(struct nvc0_clk_priv *, int);
+       } stage[] = {
+               { nvc0_clk_prog_0 }, /* div programming */
+               { nvc0_clk_prog_1 }, /* select div mode */
+               { nvc0_clk_prog_2 }, /* (maybe) program pll */
+               { nvc0_clk_prog_3 }, /* (maybe) select pll mode */
+               { nvc0_clk_prog_4 }, /* final divider */
+       };
+       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)
+                               continue;
+                       stage[i].exec(priv, j);
+               }
+       }
+
+       return 0;
+}
+
+static void
+nvc0_clk_tidy(struct nouveau_clk *clk)
+{
+       struct nvc0_clk_priv *priv = (void *)clk;
+       memset(priv->eng, 0x00, sizeof(priv->eng));
+}
+
+static struct nouveau_domain
+nvc0_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 int
+nvc0_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nvc0_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, nvc0_domain, NULL, 0,
+                                  false, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nvc0_clk_read;
+       priv->base.calc = nvc0_clk_calc;
+       priv->base.prog = nvc0_clk_prog;
+       priv->base.tidy = nvc0_clk_tidy;
+       return 0;
+}
+
+struct nouveau_oclass
+nvc0_clk_oclass = {
+       .handle = NV_SUBDEV(CLK, 0xc0),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nve0.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nve0.c
new file mode 100644 (file)
index 0000000..ffd2139
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/clk.h>
+#include <subdev/timer.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+
+#include "pll.h"
+
+struct nve0_clk_info {
+       u32 freq;
+       u32 ssel;
+       u32 mdiv;
+       u32 dsrc;
+       u32 ddiv;
+       u32 coef;
+};
+
+struct nve0_clk_priv {
+       struct nouveau_clk base;
+       struct nve0_clk_info eng[16];
+};
+
+static u32 read_div(struct nve0_clk_priv *, int, u32, u32);
+static u32 read_pll(struct nve0_clk_priv *, u32);
+
+static u32
+read_vco(struct nve0_clk_priv *priv, u32 dsrc)
+{
+       u32 ssrc = nv_rd32(priv, dsrc);
+       if (!(ssrc & 0x00000100))
+               return read_pll(priv, 0x00e800);
+       return read_pll(priv, 0x00e820);
+}
+
+static u32
+read_pll(struct nve0_clk_priv *priv, u32 pll)
+{
+       u32 ctrl = nv_rd32(priv, pll + 0x00);
+       u32 coef = nv_rd32(priv, pll + 0x04);
+       u32 P = (coef & 0x003f0000) >> 16;
+       u32 N = (coef & 0x0000ff00) >> 8;
+       u32 M = (coef & 0x000000ff) >> 0;
+       u32 sclk;
+       u16 fN = 0xf000;
+
+       if (!(ctrl & 0x00000001))
+               return 0;
+
+       switch (pll) {
+       case 0x00e800:
+       case 0x00e820:
+               sclk = nv_device(priv)->crystal;
+               P = 1;
+               break;
+       case 0x132000:
+               sclk = read_pll(priv, 0x132020);
+               P = (coef & 0x10000000) ? 2 : 1;
+               break;
+       case 0x132020:
+               sclk = read_div(priv, 0, 0x137320, 0x137330);
+               fN   = nv_rd32(priv, pll + 0x10) >> 16;
+               break;
+       case 0x137000:
+       case 0x137020:
+       case 0x137040:
+       case 0x1370e0:
+               sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140);
+               break;
+       default:
+               return 0;
+       }
+
+       if (P == 0)
+               P = 1;
+
+       sclk = (sclk * N) + (((u16)(fN + 4096) * sclk) >> 13);
+       return sclk / (M * P);
+}
+
+static u32
+read_div(struct nve0_clk_priv *priv, int doff, u32 dsrc, u32 dctl)
+{
+       u32 ssrc = nv_rd32(priv, dsrc + (doff * 4));
+       u32 sctl = nv_rd32(priv, dctl + (doff * 4));
+
+       switch (ssrc & 0x00000003) {
+       case 0:
+               if ((ssrc & 0x00030000) != 0x00030000)
+                       return nv_device(priv)->crystal;
+               return 108000;
+       case 2:
+               return 100000;
+       case 3:
+               if (sctl & 0x80000000) {
+                       u32 sclk = read_vco(priv, dsrc + (doff * 4));
+                       u32 sdiv = (sctl & 0x0000003f) + 2;
+                       return (sclk * 2) / sdiv;
+               }
+
+               return read_vco(priv, dsrc + (doff * 4));
+       default:
+               return 0;
+       }
+}
+
+static u32
+read_mem(struct nve0_clk_priv *priv)
+{
+       switch (nv_rd32(priv, 0x1373f4) & 0x0000000f) {
+       case 1: return read_pll(priv, 0x132020);
+       case 2: return read_pll(priv, 0x132000);
+       default:
+               return 0;
+       }
+}
+
+static u32
+read_clk(struct nve0_clk_priv *priv, int clk)
+{
+       u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4));
+       u32 sclk, sdiv;
+
+       if (clk < 7) {
+               u32 ssel = nv_rd32(priv, 0x137100);
+               if (ssel & (1 << clk)) {
+                       sclk = read_pll(priv, 0x137000 + (clk * 0x20));
+                       sdiv = 1;
+               } else {
+                       sclk = read_div(priv, clk, 0x137160, 0x1371d0);
+                       sdiv = 0;
+               }
+       } else {
+               u32 ssrc = nv_rd32(priv, 0x137160 + (clk * 0x04));
+               if ((ssrc & 0x00000003) == 0x00000003) {
+                       sclk = read_div(priv, clk, 0x137160, 0x1371d0);
+                       if (ssrc & 0x00000100) {
+                               if (ssrc & 0x40000000)
+                                       sclk = read_pll(priv, 0x1370e0);
+                               sdiv = 1;
+                       } else {
+                               sdiv = 0;
+                       }
+               } else {
+                       sclk = read_div(priv, clk, 0x137160, 0x1371d0);
+                       sdiv = 0;
+               }
+       }
+
+       if (sctl & 0x80000000) {
+               if (sdiv)
+                       sdiv = ((sctl & 0x00003f00) >> 8) + 2;
+               else
+                       sdiv = ((sctl & 0x0000003f) >> 0) + 2;
+               return (sclk * 2) / sdiv;
+       }
+
+       return sclk;
+}
+
+static int
+nve0_clk_read(struct nouveau_clk *clk, enum nv_clk_src src)
+{
+       struct nouveau_device *device = nv_device(clk);
+       struct nve0_clk_priv *priv = (void *)clk;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return device->crystal;
+       case nv_clk_src_href:
+               return 100000;
+       case nv_clk_src_mem:
+               return read_mem(priv);
+       case nv_clk_src_gpc:
+               return read_clk(priv, 0x00);
+       case nv_clk_src_rop:
+               return read_clk(priv, 0x01);
+       case nv_clk_src_hubk07:
+               return read_clk(priv, 0x02);
+       case nv_clk_src_hubk06:
+               return read_clk(priv, 0x07);
+       case nv_clk_src_hubk01:
+               return read_clk(priv, 0x08);
+       case nv_clk_src_daemon:
+               return read_clk(priv, 0x0c);
+       case nv_clk_src_vdec:
+               return read_clk(priv, 0x0e);
+       default:
+               nv_error(clk, "invalid clock source %d\n", src);
+               return -EINVAL;
+       }
+}
+
+static u32
+calc_div(struct nve0_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv)
+{
+       u32 div = min((ref * 2) / freq, (u32)65);
+       if (div < 2)
+               div = 2;
+
+       *ddiv = div - 2;
+       return (ref * 2) / div;
+}
+
+static u32
+calc_src(struct nve0_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
+{
+       u32 sclk;
+
+       /* use one of the fixed frequencies if possible */
+       *ddiv = 0x00000000;
+       switch (freq) {
+       case  27000:
+       case 108000:
+               *dsrc = 0x00000000;
+               if (freq == 108000)
+                       *dsrc |= 0x00030000;
+               return freq;
+       case 100000:
+               *dsrc = 0x00000002;
+               return freq;
+       default:
+               *dsrc = 0x00000003;
+               break;
+       }
+
+       /* otherwise, calculate the closest divider */
+       sclk = read_vco(priv, 0x137160 + (clk * 4));
+       if (clk < 7)
+               sclk = calc_div(priv, clk, sclk, freq, ddiv);
+       return sclk;
+}
+
+static u32
+calc_pll(struct nve0_clk_priv *priv, int clk, u32 freq, u32 *coef)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll limits;
+       int N, M, P, ret;
+
+       ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits);
+       if (ret)
+               return 0;
+
+       limits.refclk = read_div(priv, clk, 0x137120, 0x137140);
+       if (!limits.refclk)
+               return 0;
+
+       ret = nva3_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P);
+       if (ret <= 0)
+               return 0;
+
+       *coef = (P << 16) | (N << 8) | M;
+       return ret;
+}
+
+static int
+calc_clk(struct nve0_clk_priv *priv,
+        struct nouveau_cstate *cstate, int clk, int dom)
+{
+       struct nve0_clk_info *info = &priv->eng[clk];
+       u32 freq = cstate->domain[dom];
+       u32 src0, div0, div1D, div1P = 0;
+       u32 clk0, clk1 = 0;
+
+       /* invalid clock domain */
+       if (!freq)
+               return 0;
+
+       /* first possible path, using only dividers */
+       clk0 = calc_src(priv, clk, freq, &src0, &div0);
+       clk0 = calc_div(priv, clk, clk0, freq, &div1D);
+
+       /* see if we can get any closer using PLLs */
+       if (clk0 != freq && (0x0000ff87 & (1 << clk))) {
+               if (clk <= 7)
+                       clk1 = calc_pll(priv, clk, freq, &info->coef);
+               else
+                       clk1 = cstate->domain[nv_clk_src_hubk06];
+               clk1 = calc_div(priv, clk, clk1, freq, &div1P);
+       }
+
+       /* select the method which gets closest to target freq */
+       if (abs((int)freq - clk0) <= abs((int)freq - clk1)) {
+               info->dsrc = src0;
+               if (div0) {
+                       info->ddiv |= 0x80000000;
+                       info->ddiv |= div0;
+               }
+               if (div1D) {
+                       info->mdiv |= 0x80000000;
+                       info->mdiv |= div1D;
+               }
+               info->ssel = 0;
+               info->freq = clk0;
+       } else {
+               if (div1P) {
+                       info->mdiv |= 0x80000000;
+                       info->mdiv |= div1P << 8;
+               }
+               info->ssel = (1 << clk);
+               info->dsrc = 0x40000100;
+               info->freq = clk1;
+       }
+
+       return 0;
+}
+
+static int
+nve0_clk_calc(struct nouveau_clk *clk, struct nouveau_cstate *cstate)
+{
+       struct nve0_clk_priv *priv = (void *)clk;
+       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, 0x0c, nv_clk_src_daemon)) ||
+           (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec)))
+               return ret;
+
+       return 0;
+}
+
+static void
+nve0_clk_prog_0(struct nve0_clk_priv *priv, int clk)
+{
+       struct nve0_clk_info *info = &priv->eng[clk];
+       if (!info->ssel) {
+               nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x8000003f, info->ddiv);
+               nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc);
+       }
+}
+
+static void
+nve0_clk_prog_1_0(struct nve0_clk_priv *priv, int clk)
+{
+       nv_mask(priv, 0x137100, (1 << clk), 0x00000000);
+       nv_wait(priv, 0x137100, (1 << clk), 0x00000000);
+}
+
+static void
+nve0_clk_prog_1_1(struct nve0_clk_priv *priv, int clk)
+{
+       nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000000);
+}
+
+static void
+nve0_clk_prog_2(struct nve0_clk_priv *priv, int clk)
+{
+       struct nve0_clk_info *info = &priv->eng[clk];
+       const u32 addr = 0x137000 + (clk * 0x20);
+       nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000);
+       nv_mask(priv, 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);
+       }
+}
+
+static void
+nve0_clk_prog_3(struct nve0_clk_priv *priv, int clk)
+{
+       struct nve0_clk_info *info = &priv->eng[clk];
+       if (info->ssel)
+               nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f00, info->mdiv);
+       else
+               nv_mask(priv, 0x137250 + (clk * 0x04), 0x0000003f, info->mdiv);
+}
+
+static void
+nve0_clk_prog_4_0(struct nve0_clk_priv *priv, int clk)
+{
+       struct nve0_clk_info *info = &priv->eng[clk];
+       if (info->ssel) {
+               nv_mask(priv, 0x137100, (1 << clk), info->ssel);
+               nv_wait(priv, 0x137100, (1 << clk), info->ssel);
+       }
+}
+
+static void
+nve0_clk_prog_4_1(struct nve0_clk_priv *priv, int clk)
+{
+       struct nve0_clk_info *info = &priv->eng[clk];
+       if (info->ssel) {
+               nv_mask(priv, 0x137160 + (clk * 0x04), 0x40000000, 0x40000000);
+               nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000100);
+       }
+}
+
+static int
+nve0_clk_prog(struct nouveau_clk *clk)
+{
+       struct nve0_clk_priv *priv = (void *)clk;
+       struct {
+               u32 mask;
+               void (*exec)(struct nve0_clk_priv *, int);
+       } stage[] = {
+               { 0x007f, nve0_clk_prog_0   }, /* div programming */
+               { 0x007f, nve0_clk_prog_1_0 }, /* select div mode */
+               { 0xff80, nve0_clk_prog_1_1 },
+               { 0x00ff, nve0_clk_prog_2   }, /* (maybe) program pll */
+               { 0xff80, nve0_clk_prog_3   }, /* final divider */
+               { 0x007f, nve0_clk_prog_4_0 }, /* (maybe) select pll mode */
+               { 0xff80, nve0_clk_prog_4_1 },
+       };
+       int i, j;
+
+       for (i = 0; i < ARRAY_SIZE(stage); i++) {
+               for (j = 0; j < ARRAY_SIZE(priv->eng); j++) {
+                       if (!(stage[i].mask & (1 << j)))
+                               continue;
+                       if (!priv->eng[j].freq)
+                               continue;
+                       stage[i].exec(priv, j);
+               }
+       }
+
+       return 0;
+}
+
+static void
+nve0_clk_tidy(struct nouveau_clk *clk)
+{
+       struct nve0_clk_priv *priv = (void *)clk;
+       memset(priv->eng, 0x00, sizeof(priv->eng));
+}
+
+static struct nouveau_domain
+nve0_domain[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
+       { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
+       { nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
+       { nv_clk_src_mem    , 0x03, 0, "memory", 500 },
+       { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE },
+       { nv_clk_src_hubk01 , 0x05 },
+       { nv_clk_src_vdec   , 0x06 },
+       { nv_clk_src_daemon , 0x07 },
+       { nv_clk_src_max }
+};
+
+static int
+nve0_clk_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nve0_clk_priv *priv;
+       int ret;
+
+       ret = nouveau_clk_create(parent, engine, oclass, nve0_domain, NULL, 0,
+                                  true, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nve0_clk_read;
+       priv->base.calc = nve0_clk_calc;
+       priv->base.prog = nve0_clk_prog;
+       priv->base.tidy = nve0_clk_tidy;
+       return 0;
+}
+
+struct nouveau_oclass
+nve0_clk_oclass = {
+       .handle = NV_SUBDEV(CLK, 0xe0),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nve0_clk_ctor,
+               .dtor = _nouveau_clk_dtor,
+               .init = _nouveau_clk_init,
+               .fini = _nouveau_clk_fini,
+       },
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pll.h
new file mode 100644 (file)
index 0000000..445b14c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __NOUVEAU_PLL_H__
+#define __NOUVEAU_PLL_H__
+
+int nv04_pll_calc(struct nouveau_subdev *, struct nvbios_pll *, u32 freq,
+                 int *N1, int *M1, int *N2, int *M2, int *P);
+int nva3_pll_calc(struct nouveau_subdev *, struct nvbios_pll *, u32 freq,
+                 int *N, int *fN, int *M, int *P);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c
new file mode 100644 (file)
index 0000000..b47d543
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright 1993-2003 NVIDIA, Corporation
+ * Copyright 2007-2009 Stuart Bennett
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+
+#include "pll.h"
+
+static int
+getMNP_single(struct nouveau_subdev *subdev, struct nvbios_pll *info, int clk,
+             int *pN, int *pM, int *pP)
+{
+       /* Find M, N and P for a single stage PLL
+        *
+        * Note that some bioses (NV3x) have lookup tables of precomputed MNP
+        * values, but we're too lazy to use those atm
+        *
+        * "clk" parameter in kHz
+        * returns calculated clock
+        */
+       struct nouveau_bios *bios = nouveau_bios(subdev);
+       int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq;
+       int minM = info->vco1.min_m, maxM = info->vco1.max_m;
+       int minN = info->vco1.min_n, maxN = info->vco1.max_n;
+       int minU = info->vco1.min_inputfreq;
+       int maxU = info->vco1.max_inputfreq;
+       int minP = info->min_p;
+       int maxP = info->max_p_usable;
+       int crystal = info->refclk;
+       int M, N, thisP, P;
+       int clkP, calcclk;
+       int delta, bestdelta = INT_MAX;
+       int bestclk = 0;
+
+       /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */
+       /* possibly correlated with introduction of 27MHz crystal */
+       if (bios->version.major < 0x60) {
+               int cv = bios->version.chip;
+               if (cv < 0x17 || cv == 0x1a || cv == 0x20) {
+                       if (clk > 250000)
+                               maxM = 6;
+                       if (clk > 340000)
+                               maxM = 2;
+               } else if (cv < 0x40) {
+                       if (clk > 150000)
+                               maxM = 6;
+                       if (clk > 200000)
+                               maxM = 4;
+                       if (clk > 340000)
+                               maxM = 2;
+               }
+       }
+
+       P = 1 << maxP;
+       if ((clk * P) < minvco) {
+               minvco = clk * maxP;
+               maxvco = minvco * 2;
+       }
+
+       if (clk + clk/200 > maxvco)     /* +0.5% */
+               maxvco = clk + clk/200;
+
+       /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
+       for (thisP = minP; thisP <= maxP; thisP++) {
+               P = 1 << thisP;
+               clkP = clk * P;
+
+               if (clkP < minvco)
+                       continue;
+               if (clkP > maxvco)
+                       return bestclk;
+
+               for (M = minM; M <= maxM; M++) {
+                       if (crystal/M < minU)
+                               return bestclk;
+                       if (crystal/M > maxU)
+                               continue;
+
+                       /* add crystal/2 to round better */
+                       N = (clkP * M + crystal/2) / crystal;
+
+                       if (N < minN)
+                               continue;
+                       if (N > maxN)
+                               break;
+
+                       /* more rounding additions */
+                       calcclk = ((N * crystal + P/2) / P + M/2) / M;
+                       delta = abs(calcclk - clk);
+                       /* we do an exhaustive search rather than terminating
+                        * on an optimality condition...
+                        */
+                       if (delta < bestdelta) {
+                               bestdelta = delta;
+                               bestclk = calcclk;
+                               *pN = N;
+                               *pM = M;
+                               *pP = thisP;
+                               if (delta == 0) /* except this one */
+                                       return bestclk;
+                       }
+               }
+       }
+
+       return bestclk;
+}
+
+static int
+getMNP_double(struct nouveau_subdev *subdev, struct nvbios_pll *info, int clk,
+             int *pN1, int *pM1, int *pN2, int *pM2, int *pP)
+{
+       /* Find M, N and P for a two stage PLL
+        *
+        * Note that some bioses (NV30+) have lookup tables of precomputed MNP
+        * values, but we're too lazy to use those atm
+        *
+        * "clk" parameter in kHz
+        * returns calculated clock
+        */
+       int chip_version = nouveau_bios(subdev)->version.chip;
+       int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq;
+       int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq;
+       int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq;
+       int maxU1 = info->vco1.max_inputfreq, maxU2 = info->vco2.max_inputfreq;
+       int minM1 = info->vco1.min_m, maxM1 = info->vco1.max_m;
+       int minN1 = info->vco1.min_n, maxN1 = info->vco1.max_n;
+       int minM2 = info->vco2.min_m, maxM2 = info->vco2.max_m;
+       int minN2 = info->vco2.min_n, maxN2 = info->vco2.max_n;
+       int maxlog2P = info->max_p_usable;
+       int crystal = info->refclk;
+       bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2);
+       int M1, N1, M2, N2, log2P;
+       int clkP, calcclk1, calcclk2, calcclkout;
+       int delta, bestdelta = INT_MAX;
+       int bestclk = 0;
+
+       int vco2 = (maxvco2 - maxvco2/200) / 2;
+       for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++)
+               ;
+       clkP = clk << log2P;
+
+       if (maxvco2 < clk + clk/200)    /* +0.5% */
+               maxvco2 = clk + clk/200;
+
+       for (M1 = minM1; M1 <= maxM1; M1++) {
+               if (crystal/M1 < minU1)
+                       return bestclk;
+               if (crystal/M1 > maxU1)
+                       continue;
+
+               for (N1 = minN1; N1 <= maxN1; N1++) {
+                       calcclk1 = crystal * N1 / M1;
+                       if (calcclk1 < minvco1)
+                               continue;
+                       if (calcclk1 > maxvco1)
+                               break;
+
+                       for (M2 = minM2; M2 <= maxM2; M2++) {
+                               if (calcclk1/M2 < minU2)
+                                       break;
+                               if (calcclk1/M2 > maxU2)
+                                       continue;
+
+                               /* add calcclk1/2 to round better */
+                               N2 = (clkP * M2 + calcclk1/2) / calcclk1;
+                               if (N2 < minN2)
+                                       continue;
+                               if (N2 > maxN2)
+                                       break;
+
+                               if (!fixedgain2) {
+                                       if (chip_version < 0x60)
+                                               if (N2/M2 < 4 || N2/M2 > 10)
+                                                       continue;
+
+                                       calcclk2 = calcclk1 * N2 / M2;
+                                       if (calcclk2 < minvco2)
+                                               break;
+                                       if (calcclk2 > maxvco2)
+                                               continue;
+                               } else
+                                       calcclk2 = calcclk1;
+
+                               calcclkout = calcclk2 >> log2P;
+                               delta = abs(calcclkout - clk);
+                               /* we do an exhaustive search rather than terminating
+                                * on an optimality condition...
+                                */
+                               if (delta < bestdelta) {
+                                       bestdelta = delta;
+                                       bestclk = calcclkout;
+                                       *pN1 = N1;
+                                       *pM1 = M1;
+                                       *pN2 = N2;
+                                       *pM2 = M2;
+                                       *pP = log2P;
+                                       if (delta == 0) /* except this one */
+                                               return bestclk;
+                               }
+                       }
+               }
+       }
+
+       return bestclk;
+}
+
+int
+nv04_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info, u32 freq,
+             int *N1, int *M1, int *N2, int *M2, int *P)
+{
+       int ret;
+
+       if (!info->vco2.max_freq || !N2) {
+               ret = getMNP_single(subdev, info, freq, N1, M1, P);
+               if (N2) {
+                       *N2 = 1;
+                       *M2 = 1;
+               }
+       } else {
+               ret = getMNP_double(subdev, info, freq, N1, M1, N2, M2, P);
+       }
+
+       if (!ret)
+               nv_error(subdev, "unable to compute acceptable pll values\n");
+       return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnva3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnva3.c
new file mode 100644 (file)
index 0000000..bc17fcc
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/clk.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+
+#include "pll.h"
+
+int
+nva3_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info,
+             u32 freq, int *pN, int *pfN, int *pM, int *P)
+{
+       u32 best_err = ~0, err;
+       int M, lM, hM, N, fN;
+
+       *P = info->vco1.max_freq / freq;
+       if (*P > info->max_p)
+               *P = info->max_p;
+       if (*P < info->min_p)
+               *P = info->min_p;
+
+       lM = (info->refclk + info->vco1.max_inputfreq) / info->vco1.max_inputfreq;
+       lM = max(lM, (int)info->vco1.min_m);
+       hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq;
+       hM = min(hM, (int)info->vco1.max_m);
+       lM = min(lM, hM);
+
+       for (M = lM; M <= hM; M++) {
+               u32 tmp = freq * *P * M;
+               N  = tmp / info->refclk;
+               fN = tmp % info->refclk;
+
+               if (!pfN) {
+                       if (fN >= info->refclk / 2)
+                               N++;
+               } else {
+                       if (fN <  info->refclk / 2)
+                               N--;
+                       fN = tmp - (N * info->refclk);
+               }
+
+               if (N < info->vco1.min_n)
+                       continue;
+               if (N > info->vco1.max_n)
+                       break;
+
+               err = abs(freq - (info->refclk * N / M / *P));
+               if (err < best_err) {
+                       best_err = err;
+                       *pN = N;
+                       *pM = M;
+               }
+
+               if (pfN) {
+                       *pfN = ((fN << 13) + info->refclk / 2) / info->refclk;
+                       *pfN = (*pfN - 4096) & 0xffff;
+                       return freq;
+               }
+       }
+
+       if (unlikely(best_err == ~0)) {
+               nv_error(subdev, "unable to find matching pll values\n");
+               return -EINVAL;
+       }
+
+       return info->refclk * *pN / *pM / *P;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/seq.h
new file mode 100644 (file)
index 0000000..fb33f06
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __NVKM_CLK_SEQ_H__
+#define __NVKM_CLK_SEQ_H__
+
+#include <subdev/bus.h>
+#include <subdev/bus/hwsq.h>
+
+#define clk_init(s,p)       hwsq_init(&(s)->base, (p))
+#define clk_exec(s,e)       hwsq_exec(&(s)->base, (e))
+#define clk_have(s,r)       ((s)->r_##r.addr != 0x000000)
+#define clk_rd32(s,r)       hwsq_rd32(&(s)->base, &(s)->r_##r)
+#define clk_wr32(s,r,d)     hwsq_wr32(&(s)->base, &(s)->r_##r, (d))
+#define clk_mask(s,r,m,d)   hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d))
+#define clk_setf(s,f,d)     hwsq_setf(&(s)->base, (f), (d))
+#define clk_wait(s,f,d)     hwsq_wait(&(s)->base, (f), (d))
+#define clk_nsec(s,n)       hwsq_nsec(&(s)->base, (n))
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/Kbuild
deleted file mode 100644 (file)
index f0a8602..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-nvkm-y += nvkm/subdev/clock/base.o
-nvkm-y += nvkm/subdev/clock/nv04.o
-nvkm-y += nvkm/subdev/clock/nv40.o
-nvkm-y += nvkm/subdev/clock/nv50.o
-nvkm-y += nvkm/subdev/clock/nv84.o
-nvkm-y += nvkm/subdev/clock/nva3.o
-nvkm-y += nvkm/subdev/clock/nvaa.o
-nvkm-y += nvkm/subdev/clock/nvc0.o
-nvkm-y += nvkm/subdev/clock/nve0.o
-nvkm-y += nvkm/subdev/clock/gk20a.o
-nvkm-y += nvkm/subdev/clock/pllnv04.o
-nvkm-y += nvkm/subdev/clock/pllnva3.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/base.c
deleted file mode 100644 (file)
index bc095b4..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright 2013 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <core/option.h>
-
-#include <subdev/clock.h>
-#include <subdev/therm.h>
-#include <subdev/volt.h>
-#include <subdev/fb.h>
-
-#include <subdev/bios.h>
-#include <subdev/bios/boost.h>
-#include <subdev/bios/cstep.h>
-#include <subdev/bios/perf.h>
-
-/******************************************************************************
- * misc
- *****************************************************************************/
-static u32
-nouveau_clock_adjust(struct nouveau_clock *clk, bool adjust,
-                    u8 pstate, u8 domain, u32 input)
-{
-       struct nouveau_bios *bios = nouveau_bios(clk);
-       struct nvbios_boostE boostE;
-       u8  ver, hdr, cnt, len;
-       u16 data;
-
-       data = nvbios_boostEm(bios, pstate, &ver, &hdr, &cnt, &len, &boostE);
-       if (data) {
-               struct nvbios_boostS boostS;
-               u8  idx = 0, sver, shdr;
-               u16 subd;
-
-               input = max(boostE.min, input);
-               input = min(boostE.max, input);
-               do {
-                       sver = ver;
-                       shdr = hdr;
-                       subd = nvbios_boostSp(bios, idx++, data, &sver, &shdr,
-                                             cnt, len, &boostS);
-                       if (subd && boostS.domain == domain) {
-                               if (adjust)
-                                       input = input * boostS.percent / 100;
-                               input = max(boostS.min, input);
-                               input = min(boostS.max, input);
-                               break;
-                       }
-               } while (subd);
-       }
-
-       return input;
-}
-
-/******************************************************************************
- * C-States
- *****************************************************************************/
-static int
-nouveau_cstate_prog(struct nouveau_clock *clk,
-                   struct nouveau_pstate *pstate, int cstatei)
-{
-       struct nouveau_therm *ptherm = nouveau_therm(clk);
-       struct nouveau_volt *volt = nouveau_volt(clk);
-       struct nouveau_cstate *cstate;
-       int ret;
-
-       if (!list_empty(&pstate->list)) {
-               cstate = list_entry(pstate->list.prev, typeof(*cstate), head);
-       } else {
-               cstate = &pstate->base;
-       }
-
-       if (ptherm) {
-               ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1);
-               if (ret && ret != -ENODEV) {
-                       nv_error(clk, "failed to raise fan speed: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       if (volt) {
-               ret = volt->set_id(volt, cstate->voltage, +1);
-               if (ret && ret != -ENODEV) {
-                       nv_error(clk, "failed to raise voltage: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       ret = clk->calc(clk, cstate);
-       if (ret == 0) {
-               ret = clk->prog(clk);
-               clk->tidy(clk);
-       }
-
-       if (volt) {
-               ret = volt->set_id(volt, cstate->voltage, -1);
-               if (ret && ret != -ENODEV)
-                       nv_error(clk, "failed to lower voltage: %d\n", ret);
-       }
-
-       if (ptherm) {
-               ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1);
-               if (ret && ret != -ENODEV)
-                       nv_error(clk, "failed to lower fan speed: %d\n", ret);
-       }
-
-       return 0;
-}
-
-static void
-nouveau_cstate_del(struct nouveau_cstate *cstate)
-{
-       list_del(&cstate->head);
-       kfree(cstate);
-}
-
-static int
-nouveau_cstate_new(struct nouveau_clock *clk, int idx,
-                  struct nouveau_pstate *pstate)
-{
-       struct nouveau_bios *bios = nouveau_bios(clk);
-       struct nouveau_clocks *domain = clk->domains;
-       struct nouveau_cstate *cstate = NULL;
-       struct nvbios_cstepX cstepX;
-       u8  ver, hdr;
-       u16 data;
-
-       data = nvbios_cstepXp(bios, idx, &ver, &hdr, &cstepX);
-       if (!data)
-               return -ENOENT;
-
-       cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
-       if (!cstate)
-               return -ENOMEM;
-
-       *cstate = pstate->base;
-       cstate->voltage = cstepX.voltage;
-
-       while (domain && domain->name != nv_clk_src_max) {
-               if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
-                       u32 freq = nouveau_clock_adjust(clk, true,
-                                                       pstate->pstate,
-                                                       domain->bios,
-                                                       cstepX.freq);
-                       cstate->domain[domain->name] = freq;
-               }
-               domain++;
-       }
-
-       list_add(&cstate->head, &pstate->list);
-       return 0;
-}
-
-/******************************************************************************
- * P-States
- *****************************************************************************/
-static int
-nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
-{
-       struct nouveau_fb *pfb = nouveau_fb(clk);
-       struct nouveau_pstate *pstate;
-       int ret, idx = 0;
-
-       list_for_each_entry(pstate, &clk->states, head) {
-               if (idx++ == pstatei)
-                       break;
-       }
-
-       nv_debug(clk, "setting performance state %d\n", pstatei);
-       clk->pstate = pstatei;
-
-       if (pfb->ram->calc) {
-               int khz = pstate->base.domain[nv_clk_src_mem];
-               do {
-                       ret = pfb->ram->calc(pfb, khz);
-                       if (ret == 0)
-                               ret = pfb->ram->prog(pfb);
-               } while (ret > 0);
-               pfb->ram->tidy(pfb);
-       }
-
-       return nouveau_cstate_prog(clk, pstate, 0);
-}
-
-static void
-nouveau_pstate_work(struct work_struct *work)
-{
-       struct nouveau_clock *clk = container_of(work, typeof(*clk), work);
-       int pstate;
-
-       if (!atomic_xchg(&clk->waiting, 0))
-               return;
-       clk->pwrsrc = power_supply_is_system_supplied();
-
-       nv_trace(clk, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
-                clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
-                clk->astate, clk->tstate, clk->dstate);
-
-       pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
-       if (clk->state_nr && pstate != -1) {
-               pstate = (pstate < 0) ? clk->astate : pstate;
-               pstate = min(pstate, clk->state_nr - 1 - clk->tstate);
-               pstate = max(pstate, clk->dstate);
-       } else {
-               pstate = clk->pstate = -1;
-       }
-
-       nv_trace(clk, "-> %d\n", pstate);
-       if (pstate != clk->pstate) {
-               int ret = nouveau_pstate_prog(clk, pstate);
-               if (ret) {
-                       nv_error(clk, "error setting pstate %d: %d\n",
-                                pstate, ret);
-               }
-       }
-
-       wake_up_all(&clk->wait);
-       nvkm_notify_get(&clk->pwrsrc_ntfy);
-}
-
-static int
-nouveau_pstate_calc(struct nouveau_clock *clk, bool wait)
-{
-       atomic_set(&clk->waiting, 1);
-       schedule_work(&clk->work);
-       if (wait)
-               wait_event(clk->wait, !atomic_read(&clk->waiting));
-       return 0;
-}
-
-static void
-nouveau_pstate_info(struct nouveau_clock *clk, struct nouveau_pstate *pstate)
-{
-       struct nouveau_clocks *clock = clk->domains - 1;
-       struct nouveau_cstate *cstate;
-       char info[3][32] = { "", "", "" };
-       char name[4] = "--";
-       int i = -1;
-
-       if (pstate->pstate != 0xff)
-               snprintf(name, sizeof(name), "%02x", pstate->pstate);
-
-       while ((++clock)->name != nv_clk_src_max) {
-               u32 lo = pstate->base.domain[clock->name];
-               u32 hi = lo;
-               if (hi == 0)
-                       continue;
-
-               nv_debug(clk, "%02x: %10d KHz\n", clock->name, lo);
-               list_for_each_entry(cstate, &pstate->list, head) {
-                       u32 freq = cstate->domain[clock->name];
-                       lo = min(lo, freq);
-                       hi = max(hi, freq);
-                       nv_debug(clk, "%10d KHz\n", freq);
-               }
-
-               if (clock->mname && ++i < ARRAY_SIZE(info)) {
-                       lo /= clock->mdiv;
-                       hi /= clock->mdiv;
-                       if (lo == hi) {
-                               snprintf(info[i], sizeof(info[i]), "%s %d MHz",
-                                        clock->mname, lo);
-                       } else {
-                               snprintf(info[i], sizeof(info[i]),
-                                        "%s %d-%d MHz", clock->mname, lo, hi);
-                       }
-               }
-       }
-
-       nv_info(clk, "%s: %s %s %s\n", name, info[0], info[1], info[2]);
-}
-
-static void
-nouveau_pstate_del(struct nouveau_pstate *pstate)
-{
-       struct nouveau_cstate *cstate, *temp;
-
-       list_for_each_entry_safe(cstate, temp, &pstate->list, head) {
-               nouveau_cstate_del(cstate);
-       }
-
-       list_del(&pstate->head);
-       kfree(pstate);
-}
-
-static int
-nouveau_pstate_new(struct nouveau_clock *clk, int idx)
-{
-       struct nouveau_bios *bios = nouveau_bios(clk);
-       struct nouveau_clocks *domain = clk->domains - 1;
-       struct nouveau_pstate *pstate;
-       struct nouveau_cstate *cstate;
-       struct nvbios_cstepE cstepE;
-       struct nvbios_perfE perfE;
-       u8  ver, hdr, cnt, len;
-       u16 data;
-
-       data = nvbios_perfEp(bios, idx, &ver, &hdr, &cnt, &len, &perfE);
-       if (!data)
-               return -EINVAL;
-       if (perfE.pstate == 0xff)
-               return 0;
-
-       pstate = kzalloc(sizeof(*pstate), GFP_KERNEL);
-       cstate = &pstate->base;
-       if (!pstate)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&pstate->list);
-
-       pstate->pstate = perfE.pstate;
-       pstate->fanspeed = perfE.fanspeed;
-       cstate->voltage = perfE.voltage;
-       cstate->domain[nv_clk_src_core] = perfE.core;
-       cstate->domain[nv_clk_src_shader] = perfE.shader;
-       cstate->domain[nv_clk_src_mem] = perfE.memory;
-       cstate->domain[nv_clk_src_vdec] = perfE.vdec;
-       cstate->domain[nv_clk_src_dom6] = perfE.disp;
-
-       while (ver >= 0x40 && (++domain)->name != nv_clk_src_max) {
-               struct nvbios_perfS perfS;
-               u8  sver = ver, shdr = hdr;
-               u32 perfSe = nvbios_perfSp(bios, data, domain->bios,
-                                         &sver, &shdr, cnt, len, &perfS);
-               if (perfSe == 0 || sver != 0x40)
-                       continue;
-
-               if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
-                       perfS.v40.freq = nouveau_clock_adjust(clk, false,
-                                                             pstate->pstate,
-                                                             domain->bios,
-                                                             perfS.v40.freq);
-               }
-
-               cstate->domain[domain->name] = perfS.v40.freq;
-       }
-
-       data = nvbios_cstepEm(bios, pstate->pstate, &ver, &hdr, &cstepE);
-       if (data) {
-               int idx = cstepE.index;
-               do {
-                       nouveau_cstate_new(clk, idx, pstate);
-               } while(idx--);
-       }
-
-       nouveau_pstate_info(clk, pstate);
-       list_add_tail(&pstate->head, &clk->states);
-       clk->state_nr++;
-       return 0;
-}
-
-/******************************************************************************
- * Adjustment triggers
- *****************************************************************************/
-static int
-nouveau_clock_ustate_update(struct nouveau_clock *clk, int req)
-{
-       struct nouveau_pstate *pstate;
-       int i = 0;
-
-       if (!clk->allow_reclock)
-               return -ENOSYS;
-
-       if (req != -1 && req != -2) {
-               list_for_each_entry(pstate, &clk->states, head) {
-                       if (pstate->pstate == req)
-                               break;
-                       i++;
-               }
-
-               if (pstate->pstate != req)
-                       return -EINVAL;
-               req = i;
-       }
-
-       return req + 2;
-}
-
-static int
-nouveau_clock_nstate(struct nouveau_clock *clk, const char *mode, int arglen)
-{
-       int ret = 1;
-
-       if (clk->allow_reclock && !strncasecmpz(mode, "auto", arglen))
-               return -2;
-
-       if (strncasecmpz(mode, "disabled", arglen)) {
-               char save = mode[arglen];
-               long v;
-
-               ((char *)mode)[arglen] = '\0';
-               if (!kstrtol(mode, 0, &v)) {
-                       ret = nouveau_clock_ustate_update(clk, v);
-                       if (ret < 0)
-                               ret = 1;
-               }
-               ((char *)mode)[arglen] = save;
-       }
-
-       return ret - 2;
-}
-
-int
-nouveau_clock_ustate(struct nouveau_clock *clk, int req, int pwr)
-{
-       int ret = nouveau_clock_ustate_update(clk, req);
-       if (ret >= 0) {
-               if (ret -= 2, pwr) clk->ustate_ac = ret;
-               else               clk->ustate_dc = ret;
-               return nouveau_pstate_calc(clk, true);
-       }
-       return ret;
-}
-
-int
-nouveau_clock_astate(struct nouveau_clock *clk, int req, int rel, bool wait)
-{
-       if (!rel) clk->astate  = req;
-       if ( rel) clk->astate += rel;
-       clk->astate = min(clk->astate, clk->state_nr - 1);
-       clk->astate = max(clk->astate, 0);
-       return nouveau_pstate_calc(clk, wait);
-}
-
-int
-nouveau_clock_tstate(struct nouveau_clock *clk, int req, int rel)
-{
-       if (!rel) clk->tstate  = req;
-       if ( rel) clk->tstate += rel;
-       clk->tstate = min(clk->tstate, 0);
-       clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
-       return nouveau_pstate_calc(clk, true);
-}
-
-int
-nouveau_clock_dstate(struct nouveau_clock *clk, int req, int rel)
-{
-       if (!rel) clk->dstate  = req;
-       if ( rel) clk->dstate += rel;
-       clk->dstate = min(clk->dstate, clk->state_nr - 1);
-       clk->dstate = max(clk->dstate, 0);
-       return nouveau_pstate_calc(clk, true);
-}
-
-static int
-nouveau_clock_pwrsrc(struct nvkm_notify *notify)
-{
-       struct nouveau_clock *clk =
-               container_of(notify, typeof(*clk), pwrsrc_ntfy);
-       nouveau_pstate_calc(clk, false);
-       return NVKM_NOTIFY_DROP;
-}
-
-/******************************************************************************
- * subdev base class implementation
- *****************************************************************************/
-
-int
-_nouveau_clock_fini(struct nouveau_object *object, bool suspend)
-{
-       struct nouveau_clock *clk = (void *)object;
-       nvkm_notify_put(&clk->pwrsrc_ntfy);
-       return nouveau_subdev_fini(&clk->base, suspend);
-}
-
-int
-_nouveau_clock_init(struct nouveau_object *object)
-{
-       struct nouveau_clock *clk = (void *)object;
-       struct nouveau_clocks *clock = clk->domains;
-       int ret;
-
-       ret = nouveau_subdev_init(&clk->base);
-       if (ret)
-               return ret;
-
-       memset(&clk->bstate, 0x00, sizeof(clk->bstate));
-       INIT_LIST_HEAD(&clk->bstate.list);
-       clk->bstate.pstate = 0xff;
-
-       while (clock->name != nv_clk_src_max) {
-               ret = clk->read(clk, clock->name);
-               if (ret < 0) {
-                       nv_error(clk, "%02x freq unknown\n", clock->name);
-                       return ret;
-               }
-               clk->bstate.base.domain[clock->name] = ret;
-               clock++;
-       }
-
-       nouveau_pstate_info(clk, &clk->bstate);
-
-       clk->astate = clk->state_nr - 1;
-       clk->tstate = 0;
-       clk->dstate = 0;
-       clk->pstate = -1;
-       nouveau_pstate_calc(clk, true);
-       return 0;
-}
-
-void
-_nouveau_clock_dtor(struct nouveau_object *object)
-{
-       struct nouveau_clock *clk = (void *)object;
-       struct nouveau_pstate *pstate, *temp;
-
-       nvkm_notify_fini(&clk->pwrsrc_ntfy);
-
-       list_for_each_entry_safe(pstate, temp, &clk->states, head) {
-               nouveau_pstate_del(pstate);
-       }
-
-       nouveau_subdev_destroy(&clk->base);
-}
-
-int
-nouveau_clock_create_(struct nouveau_object *parent,
-                     struct nouveau_object *engine,
-                     struct nouveau_oclass *oclass,
-                     struct nouveau_clocks *clocks,
-                     struct nouveau_pstate *pstates, int nb_pstates,
-                     bool allow_reclock,
-                     int length, void **object)
-{
-       struct nouveau_device *device = nv_device(parent);
-       struct nouveau_clock *clk;
-       int ret, idx, arglen;
-       const char *mode;
-
-       ret = nouveau_subdev_create_(parent, engine, oclass, 0, "CLK",
-                                    "clock", length, object);
-       clk = *object;
-       if (ret)
-               return ret;
-
-       INIT_LIST_HEAD(&clk->states);
-       clk->domains = clocks;
-       clk->ustate_ac = -1;
-       clk->ustate_dc = -1;
-
-       INIT_WORK(&clk->work, nouveau_pstate_work);
-       init_waitqueue_head(&clk->wait);
-       atomic_set(&clk->waiting, 0);
-
-       /* If no pstates are provided, try and fetch them from the BIOS */
-       if (!pstates) {
-               idx = 0;
-               do {
-                       ret = nouveau_pstate_new(clk, idx++);
-               } while (ret == 0);
-       } else {
-               for (idx = 0; idx < nb_pstates; idx++)
-                       list_add_tail(&pstates[idx].head, &clk->states);
-               clk->state_nr = nb_pstates;
-       }
-
-       clk->allow_reclock = allow_reclock;
-
-       ret = nvkm_notify_init(NULL, &device->event, nouveau_clock_pwrsrc, true,
-                              NULL, 0, 0, &clk->pwrsrc_ntfy);
-       if (ret)
-               return ret;
-
-       mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
-       if (mode) {
-               clk->ustate_ac = nouveau_clock_nstate(clk, mode, arglen);
-               clk->ustate_dc = nouveau_clock_nstate(clk, mode, arglen);
-       }
-
-       mode = nouveau_stropt(device->cfgopt, "NvClkModeAC", &arglen);
-       if (mode)
-               clk->ustate_ac = nouveau_clock_nstate(clk, mode, arglen);
-
-       mode = nouveau_stropt(device->cfgopt, "NvClkModeDC", &arglen);
-       if (mode)
-               clk->ustate_dc = nouveau_clock_nstate(clk, mode, arglen);
-
-
-       return 0;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/gk20a.c
deleted file mode 100644 (file)
index fb4fad3..0000000
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c
- *
- */
-
-#define MHZ (1000 * 1000)
-
-#define MASK(w)        ((1 << w) - 1)
-
-#define SYS_GPCPLL_CFG_BASE                    0x00137000
-#define GPC_BCASE_GPCPLL_CFG_BASE              0x00132800
-
-#define GPCPLL_CFG             (SYS_GPCPLL_CFG_BASE + 0)
-#define GPCPLL_CFG_ENABLE      BIT(0)
-#define GPCPLL_CFG_IDDQ                BIT(1)
-#define GPCPLL_CFG_LOCK_DET_OFF        BIT(4)
-#define GPCPLL_CFG_LOCK                BIT(17)
-
-#define GPCPLL_COEFF           (SYS_GPCPLL_CFG_BASE + 4)
-#define GPCPLL_COEFF_M_SHIFT   0
-#define GPCPLL_COEFF_M_WIDTH   8
-#define GPCPLL_COEFF_N_SHIFT   8
-#define GPCPLL_COEFF_N_WIDTH   8
-#define GPCPLL_COEFF_P_SHIFT   16
-#define GPCPLL_COEFF_P_WIDTH   6
-
-#define GPCPLL_CFG2                    (SYS_GPCPLL_CFG_BASE + 0xc)
-#define GPCPLL_CFG2_SETUP2_SHIFT       16
-#define GPCPLL_CFG2_PLL_STEPA_SHIFT    24
-
-#define GPCPLL_CFG3                    (SYS_GPCPLL_CFG_BASE + 0x18)
-#define GPCPLL_CFG3_PLL_STEPB_SHIFT    16
-
-#define GPCPLL_NDIV_SLOWDOWN                   (SYS_GPCPLL_CFG_BASE + 0x1c)
-#define GPCPLL_NDIV_SLOWDOWN_NDIV_LO_SHIFT     0
-#define GPCPLL_NDIV_SLOWDOWN_NDIV_MID_SHIFT    8
-#define GPCPLL_NDIV_SLOWDOWN_STEP_SIZE_LO2MID_SHIFT    16
-#define GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT  22
-#define GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT  31
-
-#define SEL_VCO                                (SYS_GPCPLL_CFG_BASE + 0x100)
-#define SEL_VCO_GPC2CLK_OUT_SHIFT      0
-
-#define GPC2CLK_OUT                    (SYS_GPCPLL_CFG_BASE + 0x250)
-#define GPC2CLK_OUT_SDIV14_INDIV4_WIDTH        1
-#define GPC2CLK_OUT_SDIV14_INDIV4_SHIFT        31
-#define GPC2CLK_OUT_SDIV14_INDIV4_MODE 1
-#define GPC2CLK_OUT_VCODIV_WIDTH       6
-#define GPC2CLK_OUT_VCODIV_SHIFT       8
-#define GPC2CLK_OUT_VCODIV1            0
-#define GPC2CLK_OUT_VCODIV_MASK                (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << \
-                                       GPC2CLK_OUT_VCODIV_SHIFT)
-#define        GPC2CLK_OUT_BYPDIV_WIDTH        6
-#define GPC2CLK_OUT_BYPDIV_SHIFT       0
-#define GPC2CLK_OUT_BYPDIV31           0x3c
-#define GPC2CLK_OUT_INIT_MASK  ((MASK(GPC2CLK_OUT_SDIV14_INDIV4_WIDTH) << \
-               GPC2CLK_OUT_SDIV14_INDIV4_SHIFT)\
-               | (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << GPC2CLK_OUT_VCODIV_SHIFT)\
-               | (MASK(GPC2CLK_OUT_BYPDIV_WIDTH) << GPC2CLK_OUT_BYPDIV_SHIFT))
-#define GPC2CLK_OUT_INIT_VAL   ((GPC2CLK_OUT_SDIV14_INDIV4_MODE << \
-               GPC2CLK_OUT_SDIV14_INDIV4_SHIFT) \
-               | (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT) \
-               | (GPC2CLK_OUT_BYPDIV31 << GPC2CLK_OUT_BYPDIV_SHIFT))
-
-#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG  (GPC_BCASE_GPCPLL_CFG_BASE + 0xa0)
-#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT    24
-#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
-           (0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
-
-#include <subdev/clock.h>
-#include <subdev/timer.h>
-
-#ifdef __KERNEL__
-#include <nouveau_platform.h>
-#endif
-
-static const u8 pl_to_div[] = {
-/* PL:   0, 1, 2, 3, 4, 5, 6,  7,  8,  9, 10, 11, 12, 13, 14 */
-/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
-};
-
-/* All frequencies in Mhz */
-struct gk20a_clk_pllg_params {
-       u32 min_vco, max_vco;
-       u32 min_u, max_u;
-       u32 min_m, max_m;
-       u32 min_n, max_n;
-       u32 min_pl, max_pl;
-};
-
-static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
-       .min_vco = 1000, .max_vco = 2064,
-       .min_u = 12, .max_u = 38,
-       .min_m = 1, .max_m = 255,
-       .min_n = 8, .max_n = 255,
-       .min_pl = 1, .max_pl = 32,
-};
-
-struct gk20a_clock_priv {
-       struct nouveau_clock base;
-       const struct gk20a_clk_pllg_params *params;
-       u32 m, n, pl;
-       u32 parent_rate;
-};
-#define to_gk20a_clock(base) container_of(base, struct gk20a_clock_priv, base)
-
-static void
-gk20a_pllg_read_mnp(struct gk20a_clock_priv *priv)
-{
-       u32 val;
-
-       val = nv_rd32(priv, GPCPLL_COEFF);
-       priv->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
-       priv->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH);
-       priv->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
-}
-
-static u32
-gk20a_pllg_calc_rate(struct gk20a_clock_priv *priv)
-{
-       u32 rate;
-       u32 divider;
-
-       rate = priv->parent_rate * priv->n;
-       divider = priv->m * pl_to_div[priv->pl];
-       do_div(rate, divider);
-
-       return rate / 2;
-}
-
-static int
-gk20a_pllg_calc_mnp(struct gk20a_clock_priv *priv, unsigned long rate)
-{
-       u32 target_clk_f, ref_clk_f, target_freq;
-       u32 min_vco_f, max_vco_f;
-       u32 low_pl, high_pl, best_pl;
-       u32 target_vco_f, vco_f;
-       u32 best_m, best_n;
-       u32 u_f;
-       u32 m, n, n2;
-       u32 delta, lwv, best_delta = ~0;
-       u32 pl;
-
-       target_clk_f = rate * 2 / MHZ;
-       ref_clk_f = priv->parent_rate / MHZ;
-
-       max_vco_f = priv->params->max_vco;
-       min_vco_f = priv->params->min_vco;
-       best_m = priv->params->max_m;
-       best_n = priv->params->min_n;
-       best_pl = priv->params->min_pl;
-
-       target_vco_f = target_clk_f + target_clk_f / 50;
-       if (max_vco_f < target_vco_f)
-               max_vco_f = target_vco_f;
-
-       /* min_pl <= high_pl <= max_pl */
-       high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
-       high_pl = min(high_pl, priv->params->max_pl);
-       high_pl = max(high_pl, priv->params->min_pl);
-
-       /* min_pl <= low_pl <= max_pl */
-       low_pl = min_vco_f / target_vco_f;
-       low_pl = min(low_pl, priv->params->max_pl);
-       low_pl = max(low_pl, priv->params->min_pl);
-
-       /* Find Indices of high_pl and low_pl */
-       for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
-               if (pl_to_div[pl] >= low_pl) {
-                       low_pl = pl;
-                       break;
-               }
-       }
-       for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
-               if (pl_to_div[pl] >= high_pl) {
-                       high_pl = pl;
-                       break;
-               }
-       }
-
-       nv_debug(priv, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
-                pl_to_div[low_pl], high_pl, pl_to_div[high_pl]);
-
-       /* Select lowest possible VCO */
-       for (pl = low_pl; pl <= high_pl; pl++) {
-               target_vco_f = target_clk_f * pl_to_div[pl];
-               for (m = priv->params->min_m; m <= priv->params->max_m; m++) {
-                       u_f = ref_clk_f / m;
-
-                       if (u_f < priv->params->min_u)
-                               break;
-                       if (u_f > priv->params->max_u)
-                               continue;
-
-                       n = (target_vco_f * m) / ref_clk_f;
-                       n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f;
-
-                       if (n > priv->params->max_n)
-                               break;
-
-                       for (; n <= n2; n++) {
-                               if (n < priv->params->min_n)
-                                       continue;
-                               if (n > priv->params->max_n)
-                                       break;
-
-                               vco_f = ref_clk_f * n / m;
-
-                               if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
-                                       lwv = (vco_f + (pl_to_div[pl] / 2))
-                                               / pl_to_div[pl];
-                                       delta = abs(lwv - target_clk_f);
-
-                                       if (delta < best_delta) {
-                                               best_delta = delta;
-                                               best_m = m;
-                                               best_n = n;
-                                               best_pl = pl;
-
-                                               if (best_delta == 0)
-                                                       goto found_match;
-                                       }
-                               }
-                       }
-               }
-       }
-
-found_match:
-       WARN_ON(best_delta == ~0);
-
-       if (best_delta != 0)
-               nv_debug(priv, "no best match for target @ %dMHz on gpc_pll",
-                        target_clk_f);
-
-       priv->m = best_m;
-       priv->n = best_n;
-       priv->pl = best_pl;
-
-       target_freq = gk20a_pllg_calc_rate(priv) / MHZ;
-
-       nv_debug(priv, "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n",
-                target_freq, priv->m, priv->n, priv->pl, pl_to_div[priv->pl]);
-
-       return 0;
-}
-
-static int
-gk20a_pllg_slide(struct gk20a_clock_priv *priv, u32 n)
-{
-       u32 val;
-       int ramp_timeout;
-
-       /* get old coefficients */
-       val = nv_rd32(priv, GPCPLL_COEFF);
-       /* do nothing if NDIV is the same */
-       if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH)))
-               return 0;
-
-       /* setup */
-       nv_mask(priv, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
-               0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT);
-       nv_mask(priv, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
-               0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT);
-
-       /* pll slowdown mode */
-       nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
-               BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
-               BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
-
-       /* new ndiv ready for ramp */
-       val = nv_rd32(priv, GPCPLL_COEFF);
-       val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT);
-       val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
-       udelay(1);
-       nv_wr32(priv, GPCPLL_COEFF, val);
-
-       /* dynamic ramp to new ndiv */
-       val = nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
-       val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT;
-       udelay(1);
-       nv_wr32(priv, GPCPLL_NDIV_SLOWDOWN, val);
-
-       for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) {
-               udelay(1);
-               val = nv_rd32(priv, GPC_BCAST_NDIV_SLOWDOWN_DEBUG);
-               if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK)
-                       break;
-       }
-
-       /* exit slowdown mode */
-       nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
-               BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) |
-               BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
-       nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
-
-       if (ramp_timeout <= 0) {
-               nv_error(priv, "gpcpll dynamic ramp timeout\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static void
-_gk20a_pllg_enable(struct gk20a_clock_priv *priv)
-{
-       nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
-       nv_rd32(priv, GPCPLL_CFG);
-}
-
-static void
-_gk20a_pllg_disable(struct gk20a_clock_priv *priv)
-{
-       nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
-       nv_rd32(priv, GPCPLL_CFG);
-}
-
-static int
-_gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv, bool allow_slide)
-{
-       u32 val, cfg;
-       u32 m_old, pl_old, n_lo;
-
-       /* get old coefficients */
-       val = nv_rd32(priv, GPCPLL_COEFF);
-       m_old = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
-       pl_old = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
-
-       /* do NDIV slide if there is no change in M and PL */
-       cfg = nv_rd32(priv, GPCPLL_CFG);
-       if (allow_slide && priv->m == m_old && priv->pl == pl_old &&
-           (cfg & GPCPLL_CFG_ENABLE)) {
-               return gk20a_pllg_slide(priv, priv->n);
-       }
-
-       /* slide down to NDIV_LO */
-       n_lo = DIV_ROUND_UP(m_old * priv->params->min_vco,
-                           priv->parent_rate / MHZ);
-       if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) {
-               int ret = gk20a_pllg_slide(priv, n_lo);
-
-               if (ret)
-                       return ret;
-       }
-
-       /* split FO-to-bypass jump in halfs by setting out divider 1:2 */
-       nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
-               0x2 << GPC2CLK_OUT_VCODIV_SHIFT);
-
-       /* put PLL in bypass before programming it */
-       val = nv_rd32(priv, SEL_VCO);
-       val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
-       udelay(2);
-       nv_wr32(priv, SEL_VCO, val);
-
-       /* get out from IDDQ */
-       val = nv_rd32(priv, GPCPLL_CFG);
-       if (val & GPCPLL_CFG_IDDQ) {
-               val &= ~GPCPLL_CFG_IDDQ;
-               nv_wr32(priv, GPCPLL_CFG, val);
-               nv_rd32(priv, GPCPLL_CFG);
-               udelay(2);
-       }
-
-       _gk20a_pllg_disable(priv);
-
-       nv_debug(priv, "%s: m=%d n=%d pl=%d\n", __func__, priv->m, priv->n,
-                priv->pl);
-
-       n_lo = DIV_ROUND_UP(priv->m * priv->params->min_vco,
-                           priv->parent_rate / MHZ);
-       val = priv->m << GPCPLL_COEFF_M_SHIFT;
-       val |= (allow_slide ? n_lo : priv->n) << GPCPLL_COEFF_N_SHIFT;
-       val |= priv->pl << GPCPLL_COEFF_P_SHIFT;
-       nv_wr32(priv, GPCPLL_COEFF, val);
-
-       _gk20a_pllg_enable(priv);
-
-       val = nv_rd32(priv, GPCPLL_CFG);
-       if (val & GPCPLL_CFG_LOCK_DET_OFF) {
-               val &= ~GPCPLL_CFG_LOCK_DET_OFF;
-               nv_wr32(priv, GPCPLL_CFG, val);
-       }
-
-       if (!nouveau_timer_wait_eq(priv, 300000, GPCPLL_CFG, GPCPLL_CFG_LOCK,
-                                  GPCPLL_CFG_LOCK)) {
-               nv_error(priv, "%s: timeout waiting for pllg lock\n", __func__);
-               return -ETIMEDOUT;
-       }
-
-       /* switch to VCO mode */
-       nv_mask(priv, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
-
-       /* restore out divider 1:1 */
-       val = nv_rd32(priv, GPC2CLK_OUT);
-       val &= ~GPC2CLK_OUT_VCODIV_MASK;
-       udelay(2);
-       nv_wr32(priv, GPC2CLK_OUT, val);
-
-       /* slide up to new NDIV */
-       return allow_slide ? gk20a_pllg_slide(priv, priv->n) : 0;
-}
-
-static int
-gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv)
-{
-       int err;
-
-       err = _gk20a_pllg_program_mnp(priv, true);
-       if (err)
-               err = _gk20a_pllg_program_mnp(priv, false);
-
-       return err;
-}
-
-static void
-gk20a_pllg_disable(struct gk20a_clock_priv *priv)
-{
-       u32 val;
-
-       /* slide to VCO min */
-       val = nv_rd32(priv, GPCPLL_CFG);
-       if (val & GPCPLL_CFG_ENABLE) {
-               u32 coeff, m, n_lo;
-
-               coeff = nv_rd32(priv, GPCPLL_COEFF);
-               m = (coeff >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
-               n_lo = DIV_ROUND_UP(m * priv->params->min_vco,
-                                   priv->parent_rate / MHZ);
-               gk20a_pllg_slide(priv, n_lo);
-       }
-
-       /* put PLL in bypass before disabling it */
-       nv_mask(priv, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
-
-       _gk20a_pllg_disable(priv);
-}
-
-#define GK20A_CLK_GPC_MDIV 1000
-
-static struct nouveau_clocks
-gk20a_domains[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
-       { nv_clk_src_max }
-};
-
-static struct nouveau_pstate
-gk20a_pstates[] = {
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 72000,
-                       .voltage = 0,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 108000,
-                       .voltage = 1,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 180000,
-                       .voltage = 2,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 252000,
-                       .voltage = 3,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 324000,
-                       .voltage = 4,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 396000,
-                       .voltage = 5,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 468000,
-                       .voltage = 6,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 540000,
-                       .voltage = 7,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 612000,
-                       .voltage = 8,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 648000,
-                       .voltage = 9,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 684000,
-                       .voltage = 10,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 708000,
-                       .voltage = 11,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 756000,
-                       .voltage = 12,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 804000,
-                       .voltage = 13,
-               },
-       },
-       {
-               .base = {
-                       .domain[nv_clk_src_gpc] = 852000,
-                       .voltage = 14,
-               },
-       },
-};
-
-static int
-gk20a_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct gk20a_clock_priv *priv = (void *)clk;
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return nv_device(clk)->crystal;
-       case nv_clk_src_gpc:
-               gk20a_pllg_read_mnp(priv);
-               return gk20a_pllg_calc_rate(priv) / GK20A_CLK_GPC_MDIV;
-       default:
-               nv_error(clk, "invalid clock source %d\n", src);
-               return -EINVAL;
-       }
-}
-
-static int
-gk20a_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct gk20a_clock_priv *priv = (void *)clk;
-
-       return gk20a_pllg_calc_mnp(priv, cstate->domain[nv_clk_src_gpc] *
-                                        GK20A_CLK_GPC_MDIV);
-}
-
-static int
-gk20a_clock_prog(struct nouveau_clock *clk)
-{
-       struct gk20a_clock_priv *priv = (void *)clk;
-
-       return gk20a_pllg_program_mnp(priv);
-}
-
-static void
-gk20a_clock_tidy(struct nouveau_clock *clk)
-{
-}
-
-static int
-gk20a_clock_fini(struct nouveau_object *object, bool suspend)
-{
-       struct gk20a_clock_priv *priv = (void *)object;
-       int ret;
-
-       ret = nouveau_clock_fini(&priv->base, false);
-
-       gk20a_pllg_disable(priv);
-
-       return ret;
-}
-
-static int
-gk20a_clock_init(struct nouveau_object *object)
-{
-       struct gk20a_clock_priv *priv = (void *)object;
-       int ret;
-
-       nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL);
-
-       ret = nouveau_clock_init(&priv->base);
-       if (ret)
-               return ret;
-
-       ret = gk20a_clock_prog(&priv->base);
-       if (ret) {
-               nv_error(priv, "cannot initialize clock\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int
-gk20a_clock_ctor(struct nouveau_object *parent,  struct nouveau_object *engine,
-                struct nouveau_oclass *oclass, void *data, u32 size,
-                struct nouveau_object **pobject)
-{
-       struct gk20a_clock_priv *priv;
-       struct nouveau_platform_device *plat;
-       int ret;
-       int i;
-
-       /* Finish initializing the pstates */
-       for (i = 0; i < ARRAY_SIZE(gk20a_pstates); i++) {
-               INIT_LIST_HEAD(&gk20a_pstates[i].list);
-               gk20a_pstates[i].pstate = i + 1;
-       }
-
-       ret = nouveau_clock_create(parent, engine, oclass, gk20a_domains,
-                       gk20a_pstates, ARRAY_SIZE(gk20a_pstates), true, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->params = &gk20a_pllg_params;
-
-       plat = nv_device_to_platform(nv_device(parent));
-       priv->parent_rate = clk_get_rate(plat->gpu->clk);
-       nv_info(priv, "parent clock rate: %d Mhz\n", priv->parent_rate / MHZ);
-
-       priv->base.read = gk20a_clock_read;
-       priv->base.calc = gk20a_clock_calc;
-       priv->base.prog = gk20a_clock_prog;
-       priv->base.tidy = gk20a_clock_tidy;
-
-       return 0;
-}
-
-struct nouveau_oclass
-gk20a_clock_oclass = {
-       .handle = NV_SUBDEV(CLOCK, 0xea),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = gk20a_clock_ctor,
-               .dtor = _nouveau_subdev_dtor,
-               .init = gk20a_clock_init,
-               .fini = gk20a_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv04.c
deleted file mode 100644 (file)
index 4c48232..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-#include <subdev/clock.h>
-#include <subdev/devinit/nv04.h>
-
-#include "pll.h"
-
-struct nv04_clock_priv {
-       struct nouveau_clock base;
-};
-
-int
-nv04_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info,
-                   int clk, struct nouveau_pll_vals *pv)
-{
-       int N1, M1, N2, M2, P;
-       int ret = nv04_pll_calc(nv_subdev(clock), info, clk, &N1, &M1, &N2, &M2, &P);
-       if (ret) {
-               pv->refclk = info->refclk;
-               pv->N1 = N1;
-               pv->M1 = M1;
-               pv->N2 = N2;
-               pv->M2 = M2;
-               pv->log2P = P;
-       }
-       return ret;
-}
-
-int
-nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1,
-                   struct nouveau_pll_vals *pv)
-{
-       struct nouveau_devinit *devinit = nouveau_devinit(clk);
-       int cv = nouveau_bios(clk)->version.chip;
-
-       if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
-           cv >= 0x40) {
-               if (reg1 > 0x405c)
-                       setPLL_double_highregs(devinit, reg1, pv);
-               else
-                       setPLL_double_lowregs(devinit, reg1, pv);
-       } else
-               setPLL_single(devinit, reg1, pv);
-
-       return 0;
-}
-
-static struct nouveau_clocks
-nv04_domain[] = {
-       { nv_clk_src_max }
-};
-
-static int
-nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nv04_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, NULL, 0,
-                                  false, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.pll_calc = nv04_clock_pll_calc;
-       priv->base.pll_prog = nv04_clock_pll_prog;
-       return 0;
-}
-
-struct nouveau_oclass
-nv04_clock_oclass = {
-       .handle = NV_SUBDEV(CLOCK, 0x04),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv04_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv40.c
deleted file mode 100644 (file)
index 08368fe..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/clock.h>
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-
-#include "pll.h"
-
-struct nv40_clock_priv {
-       struct nouveau_clock base;
-       u32 ctrl;
-       u32 npll_ctrl;
-       u32 npll_coef;
-       u32 spll;
-};
-
-static struct nouveau_clocks
-nv40_domain[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_href   , 0xff },
-       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
-       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
-       { nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
-       { nv_clk_src_max }
-};
-
-static u32
-read_pll_1(struct nv40_clock_priv *priv, u32 reg)
-{
-       u32 ctrl = nv_rd32(priv, reg + 0x00);
-       int P = (ctrl & 0x00070000) >> 16;
-       int N = (ctrl & 0x0000ff00) >> 8;
-       int M = (ctrl & 0x000000ff) >> 0;
-       u32 ref = 27000, clk = 0;
-
-       if (ctrl & 0x80000000)
-               clk = ref * N / M;
-
-       return clk >> P;
-}
-
-static u32
-read_pll_2(struct nv40_clock_priv *priv, u32 reg)
-{
-       u32 ctrl = nv_rd32(priv, reg + 0x00);
-       u32 coef = nv_rd32(priv, reg + 0x04);
-       int N2 = (coef & 0xff000000) >> 24;
-       int M2 = (coef & 0x00ff0000) >> 16;
-       int N1 = (coef & 0x0000ff00) >> 8;
-       int M1 = (coef & 0x000000ff) >> 0;
-       int P = (ctrl & 0x00070000) >> 16;
-       u32 ref = 27000, clk = 0;
-
-       if ((ctrl & 0x80000000) && M1) {
-               clk = ref * N1 / M1;
-               if ((ctrl & 0x40000100) == 0x40000000) {
-                       if (M2)
-                               clk = clk * N2 / M2;
-                       else
-                               clk = 0;
-               }
-       }
-
-       return clk >> P;
-}
-
-static u32
-read_clk(struct nv40_clock_priv *priv, u32 src)
-{
-       switch (src) {
-       case 3:
-               return read_pll_2(priv, 0x004000);
-       case 2:
-               return read_pll_1(priv, 0x004008);
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static int
-nv40_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct nv40_clock_priv *priv = (void *)clk;
-       u32 mast = nv_rd32(priv, 0x00c040);
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return nv_device(priv)->crystal;
-       case nv_clk_src_href:
-               return 100000; /*XXX: PCIE/AGP differ*/
-       case nv_clk_src_core:
-               return read_clk(priv, (mast & 0x00000003) >> 0);
-       case nv_clk_src_shader:
-               return read_clk(priv, (mast & 0x00000030) >> 4);
-       case nv_clk_src_mem:
-               return read_pll_2(priv, 0x4020);
-       default:
-               break;
-       }
-
-       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
-       return -EINVAL;
-}
-
-static int
-nv40_clock_calc_pll(struct nv40_clock_priv *priv, u32 reg, u32 clk,
-                   int *N1, int *M1, int *N2, int *M2, int *log2P)
-{
-       struct nouveau_bios *bios = nouveau_bios(priv);
-       struct nvbios_pll pll;
-       int ret;
-
-       ret = nvbios_pll_parse(bios, reg, &pll);
-       if (ret)
-               return ret;
-
-       if (clk < pll.vco1.max_freq)
-               pll.vco2.max_freq = 0;
-
-       ret = nv04_pll_calc(nv_subdev(priv), &pll, clk, N1, M1, N2, M2, log2P);
-       if (ret == 0)
-               return -ERANGE;
-       return ret;
-}
-
-static int
-nv40_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct nv40_clock_priv *priv = (void *)clk;
-       int gclk = cstate->domain[nv_clk_src_core];
-       int sclk = cstate->domain[nv_clk_src_shader];
-       int N1, M1, N2, M2, log2P;
-       int ret;
-
-       /* core/geometric clock */
-       ret = nv40_clock_calc_pll(priv, 0x004000, gclk,
-                                &N1, &M1, &N2, &M2, &log2P);
-       if (ret < 0)
-               return ret;
-
-       if (N2 == M2) {
-               priv->npll_ctrl = 0x80000100 | (log2P << 16);
-               priv->npll_coef = (N1 << 8) | M1;
-       } else {
-               priv->npll_ctrl = 0xc0000000 | (log2P << 16);
-               priv->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
-       }
-
-       /* use the second pll for shader/rop clock, if it differs from core */
-       if (sclk && sclk != gclk) {
-               ret = nv40_clock_calc_pll(priv, 0x004008, sclk,
-                                        &N1, &M1, NULL, NULL, &log2P);
-               if (ret < 0)
-                       return ret;
-
-               priv->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
-               priv->ctrl = 0x00000223;
-       } else {
-               priv->spll = 0x00000000;
-               priv->ctrl = 0x00000333;
-       }
-
-       return 0;
-}
-
-static int
-nv40_clock_prog(struct nouveau_clock *clk)
-{
-       struct nv40_clock_priv *priv = (void *)clk;
-       nv_mask(priv, 0x00c040, 0x00000333, 0x00000000);
-       nv_wr32(priv, 0x004004, priv->npll_coef);
-       nv_mask(priv, 0x004000, 0xc0070100, priv->npll_ctrl);
-       nv_mask(priv, 0x004008, 0xc007ffff, priv->spll);
-       mdelay(5);
-       nv_mask(priv, 0x00c040, 0x00000333, priv->ctrl);
-       return 0;
-}
-
-static void
-nv40_clock_tidy(struct nouveau_clock *clk)
-{
-}
-
-static int
-nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nv40_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, NULL, 0,
-                                  true, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.pll_calc = nv04_clock_pll_calc;
-       priv->base.pll_prog = nv04_clock_pll_prog;
-       priv->base.read = nv40_clock_read;
-       priv->base.calc = nv40_clock_calc;
-       priv->base.prog = nv40_clock_prog;
-       priv->base.tidy = nv40_clock_tidy;
-       return 0;
-}
-
-struct nouveau_oclass
-nv40_clock_oclass = {
-       .handle = NV_SUBDEV(CLOCK, 0x40),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv40_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv50.c
deleted file mode 100644 (file)
index 5070ebc..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-
-#include "nv50.h"
-#include "pll.h"
-#include "seq.h"
-
-static u32
-read_div(struct nv50_clock_priv *priv)
-{
-       switch (nv_device(priv)->chipset) {
-       case 0x50: /* it exists, but only has bit 31, not the dividers.. */
-       case 0x84:
-       case 0x86:
-       case 0x98:
-       case 0xa0:
-               return nv_rd32(priv, 0x004700);
-       case 0x92:
-       case 0x94:
-       case 0x96:
-               return nv_rd32(priv, 0x004800);
-       default:
-               return 0x00000000;
-       }
-}
-
-static u32
-read_pll_src(struct nv50_clock_priv *priv, u32 base)
-{
-       struct nouveau_clock *clk = &priv->base;
-       u32 coef, ref = clk->read(clk, nv_clk_src_crystal);
-       u32 rsel = nv_rd32(priv, 0x00e18c);
-       int P, N, M, id;
-
-       switch (nv_device(priv)->chipset) {
-       case 0x50:
-       case 0xa0:
-               switch (base) {
-               case 0x4020:
-               case 0x4028: id = !!(rsel & 0x00000004); break;
-               case 0x4008: id = !!(rsel & 0x00000008); break;
-               case 0x4030: id = 0; break;
-               default:
-                       nv_error(priv, "ref: bad pll 0x%06x\n", base);
-                       return 0;
-               }
-
-               coef = nv_rd32(priv, 0x00e81c + (id * 0x0c));
-               ref *=  (coef & 0x01000000) ? 2 : 4;
-               P    =  (coef & 0x00070000) >> 16;
-               N    = ((coef & 0x0000ff00) >> 8) + 1;
-               M    = ((coef & 0x000000ff) >> 0) + 1;
-               break;
-       case 0x84:
-       case 0x86:
-       case 0x92:
-               coef = nv_rd32(priv, 0x00e81c);
-               P    = (coef & 0x00070000) >> 16;
-               N    = (coef & 0x0000ff00) >> 8;
-               M    = (coef & 0x000000ff) >> 0;
-               break;
-       case 0x94:
-       case 0x96:
-       case 0x98:
-               rsel = nv_rd32(priv, 0x00c050);
-               switch (base) {
-               case 0x4020: rsel = (rsel & 0x00000003) >> 0; break;
-               case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break;
-               case 0x4028: rsel = (rsel & 0x00001800) >> 11; break;
-               case 0x4030: rsel = 3; break;
-               default:
-                       nv_error(priv, "ref: bad pll 0x%06x\n", base);
-                       return 0;
-               }
-
-               switch (rsel) {
-               case 0: id = 1; break;
-               case 1: return clk->read(clk, nv_clk_src_crystal);
-               case 2: return clk->read(clk, nv_clk_src_href);
-               case 3: id = 0; break;
-               }
-
-               coef =  nv_rd32(priv, 0x00e81c + (id * 0x28));
-               P    = (nv_rd32(priv, 0x00e824 + (id * 0x28)) >> 16) & 7;
-               P   += (coef & 0x00070000) >> 16;
-               N    = (coef & 0x0000ff00) >> 8;
-               M    = (coef & 0x000000ff) >> 0;
-               break;
-       default:
-               BUG_ON(1);
-       }
-
-       if (M)
-               return (ref * N / M) >> P;
-       return 0;
-}
-
-static u32
-read_pll_ref(struct nv50_clock_priv *priv, u32 base)
-{
-       struct nouveau_clock *clk = &priv->base;
-       u32 src, mast = nv_rd32(priv, 0x00c040);
-
-       switch (base) {
-       case 0x004028:
-               src = !!(mast & 0x00200000);
-               break;
-       case 0x004020:
-               src = !!(mast & 0x00400000);
-               break;
-       case 0x004008:
-               src = !!(mast & 0x00010000);
-               break;
-       case 0x004030:
-               src = !!(mast & 0x02000000);
-               break;
-       case 0x00e810:
-               return clk->read(clk, nv_clk_src_crystal);
-       default:
-               nv_error(priv, "bad pll 0x%06x\n", base);
-               return 0;
-       }
-
-       if (src)
-               return clk->read(clk, nv_clk_src_href);
-       return read_pll_src(priv, base);
-}
-
-static u32
-read_pll(struct nv50_clock_priv *priv, u32 base)
-{
-       struct nouveau_clock *clk = &priv->base;
-       u32 mast = nv_rd32(priv, 0x00c040);
-       u32 ctrl = nv_rd32(priv, base + 0);
-       u32 coef = nv_rd32(priv, base + 4);
-       u32 ref = read_pll_ref(priv, base);
-       u32 freq = 0;
-       int N1, N2, M1, M2;
-
-       if (base == 0x004028 && (mast & 0x00100000)) {
-               /* wtf, appears to only disable post-divider on nva0 */
-               if (nv_device(priv)->chipset != 0xa0)
-                       return clk->read(clk, nv_clk_src_dom6);
-       }
-
-       N2 = (coef & 0xff000000) >> 24;
-       M2 = (coef & 0x00ff0000) >> 16;
-       N1 = (coef & 0x0000ff00) >> 8;
-       M1 = (coef & 0x000000ff);
-       if ((ctrl & 0x80000000) && M1) {
-               freq = ref * N1 / M1;
-               if ((ctrl & 0x40000100) == 0x40000000) {
-                       if (M2)
-                               freq = freq * N2 / M2;
-                       else
-                               freq = 0;
-               }
-       }
-
-       return freq;
-}
-
-static int
-nv50_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct nv50_clock_priv *priv = (void *)clk;
-       u32 mast = nv_rd32(priv, 0x00c040);
-       u32 P = 0;
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return nv_device(priv)->crystal;
-       case nv_clk_src_href:
-               return 100000; /* PCIE reference clock */
-       case nv_clk_src_hclk:
-               return div_u64((u64)clk->read(clk, nv_clk_src_href) * 27778, 10000);
-       case nv_clk_src_hclkm3:
-               return clk->read(clk, nv_clk_src_hclk) * 3;
-       case nv_clk_src_hclkm3d2:
-               return clk->read(clk, nv_clk_src_hclk) * 3 / 2;
-       case nv_clk_src_host:
-               switch (mast & 0x30000000) {
-               case 0x00000000: return clk->read(clk, nv_clk_src_href);
-               case 0x10000000: break;
-               case 0x20000000: /* !0x50 */
-               case 0x30000000: return clk->read(clk, nv_clk_src_hclk);
-               }
-               break;
-       case nv_clk_src_core:
-               if (!(mast & 0x00100000))
-                       P = (nv_rd32(priv, 0x004028) & 0x00070000) >> 16;
-               switch (mast & 0x00000003) {
-               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
-               case 0x00000001: return clk->read(clk, nv_clk_src_dom6);
-               case 0x00000002: return read_pll(priv, 0x004020) >> P;
-               case 0x00000003: return read_pll(priv, 0x004028) >> P;
-               }
-               break;
-       case nv_clk_src_shader:
-               P = (nv_rd32(priv, 0x004020) & 0x00070000) >> 16;
-               switch (mast & 0x00000030) {
-               case 0x00000000:
-                       if (mast & 0x00000080)
-                               return clk->read(clk, nv_clk_src_host) >> P;
-                       return clk->read(clk, nv_clk_src_crystal) >> P;
-               case 0x00000010: break;
-               case 0x00000020: return read_pll(priv, 0x004028) >> P;
-               case 0x00000030: return read_pll(priv, 0x004020) >> P;
-               }
-               break;
-       case nv_clk_src_mem:
-               P = (nv_rd32(priv, 0x004008) & 0x00070000) >> 16;
-               if (nv_rd32(priv, 0x004008) & 0x00000200) {
-                       switch (mast & 0x0000c000) {
-                       case 0x00000000:
-                               return clk->read(clk, nv_clk_src_crystal) >> P;
-                       case 0x00008000:
-                       case 0x0000c000:
-                               return clk->read(clk, nv_clk_src_href) >> P;
-                       }
-               } else {
-                       return read_pll(priv, 0x004008) >> P;
-               }
-               break;
-       case nv_clk_src_vdec:
-               P = (read_div(priv) & 0x00000700) >> 8;
-               switch (nv_device(priv)->chipset) {
-               case 0x84:
-               case 0x86:
-               case 0x92:
-               case 0x94:
-               case 0x96:
-               case 0xa0:
-                       switch (mast & 0x00000c00) {
-                       case 0x00000000:
-                               if (nv_device(priv)->chipset == 0xa0) /* wtf?? */
-                                       return clk->read(clk, nv_clk_src_core) >> P;
-                               return clk->read(clk, nv_clk_src_crystal) >> P;
-                       case 0x00000400:
-                               return 0;
-                       case 0x00000800:
-                               if (mast & 0x01000000)
-                                       return read_pll(priv, 0x004028) >> P;
-                               return read_pll(priv, 0x004030) >> P;
-                       case 0x00000c00:
-                               return clk->read(clk, nv_clk_src_core) >> P;
-                       }
-                       break;
-               case 0x98:
-                       switch (mast & 0x00000c00) {
-                       case 0x00000000:
-                               return clk->read(clk, nv_clk_src_core) >> P;
-                       case 0x00000400:
-                               return 0;
-                       case 0x00000800:
-                               return clk->read(clk, nv_clk_src_hclkm3d2) >> P;
-                       case 0x00000c00:
-                               return clk->read(clk, nv_clk_src_mem) >> P;
-                       }
-                       break;
-               }
-               break;
-       case nv_clk_src_dom6:
-               switch (nv_device(priv)->chipset) {
-               case 0x50:
-               case 0xa0:
-                       return read_pll(priv, 0x00e810) >> 2;
-               case 0x84:
-               case 0x86:
-               case 0x92:
-               case 0x94:
-               case 0x96:
-               case 0x98:
-                       P = (read_div(priv) & 0x00000007) >> 0;
-                       switch (mast & 0x0c000000) {
-                       case 0x00000000: return clk->read(clk, nv_clk_src_href);
-                       case 0x04000000: break;
-                       case 0x08000000: return clk->read(clk, nv_clk_src_hclk);
-                       case 0x0c000000:
-                               return clk->read(clk, nv_clk_src_hclkm3) >> P;
-                       }
-                       break;
-               default:
-                       break;
-               }
-       default:
-               break;
-       }
-
-       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
-       return -EINVAL;
-}
-
-static u32
-calc_pll(struct nv50_clock_priv *priv, u32 reg, u32 clk, int *N, int *M, int *P)
-{
-       struct nouveau_bios *bios = nouveau_bios(priv);
-       struct nvbios_pll pll;
-       int ret;
-
-       ret = nvbios_pll_parse(bios, reg, &pll);
-       if (ret)
-               return 0;
-
-       pll.vco2.max_freq = 0;
-       pll.refclk = read_pll_ref(priv, reg);
-       if (!pll.refclk)
-               return 0;
-
-       return nv04_pll_calc(nv_subdev(priv), &pll, clk, N, M, NULL, NULL, P);
-}
-
-static inline u32
-calc_div(u32 src, u32 target, int *div)
-{
-       u32 clk0 = src, clk1 = src;
-       for (*div = 0; *div <= 7; (*div)++) {
-               if (clk0 <= target) {
-                       clk1 = clk0 << (*div ? 1 : 0);
-                       break;
-               }
-               clk0 >>= 1;
-       }
-
-       if (target - clk0 <= clk1 - target)
-               return clk0;
-       (*div)--;
-       return clk1;
-}
-
-static inline u32
-clk_same(u32 a, u32 b)
-{
-       return ((a / 1000) == (b / 1000));
-}
-
-static int
-nv50_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct nv50_clock_priv *priv = (void *)clk;
-       struct nv50_clock_hwsq *hwsq = &priv->hwsq;
-       const int shader = cstate->domain[nv_clk_src_shader];
-       const int core = cstate->domain[nv_clk_src_core];
-       const int vdec = cstate->domain[nv_clk_src_vdec];
-       const int dom6 = cstate->domain[nv_clk_src_dom6];
-       u32 mastm = 0, mastv = 0;
-       u32 divsm = 0, divsv = 0;
-       int N, M, P1, P2;
-       int freq, out;
-
-       /* prepare a hwsq script from which we'll perform the reclock */
-       out = clk_init(hwsq, nv_subdev(clk));
-       if (out)
-               return out;
-
-       clk_wr32(hwsq, fifo, 0x00000001); /* block fifo */
-       clk_nsec(hwsq, 8000);
-       clk_setf(hwsq, 0x10, 0x00); /* disable fb */
-       clk_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */
-
-       /* vdec: avoid modifying xpll until we know exactly how the other
-        * clock domains work, i suspect at least some of them can also be
-        * tied to xpll...
-        */
-       if (vdec) {
-               /* see how close we can get using nvclk as a source */
-               freq = calc_div(core, vdec, &P1);
-
-               /* see how close we can get using xpll/hclk as a source */
-               if (nv_device(priv)->chipset != 0x98)
-                       out = read_pll(priv, 0x004030);
-               else
-                       out = clk->read(clk, nv_clk_src_hclkm3d2);
-               out = calc_div(out, vdec, &P2);
-
-               /* select whichever gets us closest */
-               if (abs(vdec - freq) <= abs(vdec - out)) {
-                       if (nv_device(priv)->chipset != 0x98)
-                               mastv |= 0x00000c00;
-                       divsv |= P1 << 8;
-               } else {
-                       mastv |= 0x00000800;
-                       divsv |= P2 << 8;
-               }
-
-               mastm |= 0x00000c00;
-               divsm |= 0x00000700;
-       }
-
-       /* dom6: nfi what this is, but we're limited to various combinations
-        * of the host clock frequency
-        */
-       if (dom6) {
-               if (clk_same(dom6, clk->read(clk, nv_clk_src_href))) {
-                       mastv |= 0x00000000;
-               } else
-               if (clk_same(dom6, clk->read(clk, nv_clk_src_hclk))) {
-                       mastv |= 0x08000000;
-               } else {
-                       freq = clk->read(clk, nv_clk_src_hclk) * 3;
-                       freq = calc_div(freq, dom6, &P1);
-
-                       mastv |= 0x0c000000;
-                       divsv |= P1;
-               }
-
-               mastm |= 0x0c000000;
-               divsm |= 0x00000007;
-       }
-
-       /* vdec/dom6: switch to "safe" clocks temporarily, update dividers
-        * and then switch to target clocks
-        */
-       clk_mask(hwsq, mast, mastm, 0x00000000);
-       clk_mask(hwsq, divs, divsm, divsv);
-       clk_mask(hwsq, mast, mastm, mastv);
-
-       /* core/shader: disconnect nvclk/sclk from their PLLs (nvclk to dom6,
-        * sclk to hclk) before reprogramming
-        */
-       if (nv_device(priv)->chipset < 0x92)
-               clk_mask(hwsq, mast, 0x001000b0, 0x00100080);
-       else
-               clk_mask(hwsq, mast, 0x000000b3, 0x00000081);
-
-       /* core: for the moment at least, always use nvpll */
-       freq = calc_pll(priv, 0x4028, core, &N, &M, &P1);
-       if (freq == 0)
-               return -ERANGE;
-
-       clk_mask(hwsq, nvpll[0], 0xc03f0100,
-                                0x80000000 | (P1 << 19) | (P1 << 16));
-       clk_mask(hwsq, nvpll[1], 0x0000ffff, (N << 8) | M);
-
-       /* shader: tie to nvclk if possible, otherwise use spll.  have to be
-        * very careful that the shader clock is at least twice the core, or
-        * some chipsets will be very unhappy.  i expect most or all of these
-        * cases will be handled by tying to nvclk, but it's possible there's
-        * corners
-        */
-       if (P1-- && shader == (core << 1)) {
-               clk_mask(hwsq, spll[0], 0xc03f0100, (P1 << 19) | (P1 << 16));
-               clk_mask(hwsq, mast, 0x00100033, 0x00000023);
-       } else {
-               freq = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
-               if (freq == 0)
-                       return -ERANGE;
-
-               clk_mask(hwsq, spll[0], 0xc03f0100,
-                                       0x80000000 | (P1 << 19) | (P1 << 16));
-               clk_mask(hwsq, spll[1], 0x0000ffff, (N << 8) | M);
-               clk_mask(hwsq, mast, 0x00100033, 0x00000033);
-       }
-
-       /* restore normal operation */
-       clk_setf(hwsq, 0x10, 0x01); /* enable fb */
-       clk_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */
-       clk_wr32(hwsq, fifo, 0x00000000); /* un-block fifo */
-       return 0;
-}
-
-static int
-nv50_clock_prog(struct nouveau_clock *clk)
-{
-       struct nv50_clock_priv *priv = (void *)clk;
-       return clk_exec(&priv->hwsq, true);
-}
-
-static void
-nv50_clock_tidy(struct nouveau_clock *clk)
-{
-       struct nv50_clock_priv *priv = (void *)clk;
-       clk_exec(&priv->hwsq, false);
-}
-
-int
-nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nv50_clock_oclass *pclass = (void *)oclass;
-       struct nv50_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
-                                  NULL, 0, false, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->hwsq.r_fifo = hwsq_reg(0x002504);
-       priv->hwsq.r_spll[0] = hwsq_reg(0x004020);
-       priv->hwsq.r_spll[1] = hwsq_reg(0x004024);
-       priv->hwsq.r_nvpll[0] = hwsq_reg(0x004028);
-       priv->hwsq.r_nvpll[1] = hwsq_reg(0x00402c);
-       switch (nv_device(priv)->chipset) {
-       case 0x92:
-       case 0x94:
-       case 0x96:
-               priv->hwsq.r_divs = hwsq_reg(0x004800);
-               break;
-       default:
-               priv->hwsq.r_divs = hwsq_reg(0x004700);
-               break;
-       }
-       priv->hwsq.r_mast = hwsq_reg(0x00c040);
-
-       priv->base.read = nv50_clock_read;
-       priv->base.calc = nv50_clock_calc;
-       priv->base.prog = nv50_clock_prog;
-       priv->base.tidy = nv50_clock_tidy;
-       return 0;
-}
-
-static struct nouveau_clocks
-nv50_domains[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_href   , 0xff },
-       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
-       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
-       { nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
-       { nv_clk_src_max }
-};
-
-struct nouveau_oclass *
-nv50_clock_oclass = &(struct nv50_clock_oclass) {
-       .base.handle = NV_SUBDEV(CLOCK, 0x50),
-       .base.ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv50_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-       .domains = nv50_domains,
-}.base;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv50.h
deleted file mode 100644 (file)
index f10917d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __NVKM_CLK_NV50_H__
-#define __NVKM_CLK_NV50_H__
-
-#include <subdev/bus.h>
-#include <subdev/bus/hwsq.h>
-#include <subdev/clock.h>
-
-struct nv50_clock_hwsq {
-       struct hwsq base;
-       struct hwsq_reg r_fifo;
-       struct hwsq_reg r_spll[2];
-       struct hwsq_reg r_nvpll[2];
-       struct hwsq_reg r_divs;
-       struct hwsq_reg r_mast;
-};
-
-struct nv50_clock_priv {
-       struct nouveau_clock base;
-       struct nv50_clock_hwsq hwsq;
-};
-
-int  nv50_clock_ctor(struct nouveau_object *, struct nouveau_object *,
-                    struct nouveau_oclass *, void *, u32,
-                    struct nouveau_object **);
-
-struct nv50_clock_oclass {
-       struct nouveau_oclass base;
-       struct nouveau_clocks *domains;
-};
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nv84.c
deleted file mode 100644 (file)
index b0b7c14..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2013 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs <bskeggs@redhat.com>
- */
-
-#include "nv50.h"
-
-static struct nouveau_clocks
-nv84_domains[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_href   , 0xff },
-       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
-       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
-       { nv_clk_src_mem    , 0xff, 0, "memory", 1000 },
-       { nv_clk_src_vdec   , 0xff },
-       { nv_clk_src_max }
-};
-
-struct nouveau_oclass *
-nv84_clock_oclass = &(struct nv50_clock_oclass) {
-       .base.handle = NV_SUBDEV(CLOCK, 0x84),
-       .base.ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv50_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-       .domains = nv84_domains,
-}.base;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nva3.c
deleted file mode 100644 (file)
index 07ad012..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- *          Roy Spliet
- */
-
-#include <engine/fifo.h>
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-#include <subdev/timer.h>
-
-#include "pll.h"
-
-#include "nva3.h"
-
-struct nva3_clock_priv {
-       struct nouveau_clock base;
-       struct nva3_clock_info eng[nv_clk_src_max];
-};
-
-static u32 read_clk(struct nva3_clock_priv *, int, bool);
-static u32 read_pll(struct nva3_clock_priv *, int, u32);
-
-static u32
-read_vco(struct nva3_clock_priv *priv, int clk)
-{
-       u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4));
-
-       switch (sctl & 0x00000030) {
-       case 0x00000000:
-               return nv_device(priv)->crystal;
-       case 0x00000020:
-               return read_pll(priv, 0x41, 0x00e820);
-       case 0x00000030:
-               return read_pll(priv, 0x42, 0x00e8a0);
-       default:
-               return 0;
-       }
-}
-
-static u32
-read_clk(struct nva3_clock_priv *priv, int clk, bool ignore_en)
-{
-       u32 sctl, sdiv, sclk;
-
-       /* refclk for the 0xe8xx plls is a fixed frequency */
-       if (clk >= 0x40) {
-               if (nv_device(priv)->chipset == 0xaf) {
-                       /* no joke.. seriously.. sigh.. */
-                       return nv_rd32(priv, 0x00471c) * 1000;
-               }
-
-               return nv_device(priv)->crystal;
-       }
-
-       sctl = nv_rd32(priv, 0x4120 + (clk * 4));
-       if (!ignore_en && !(sctl & 0x00000100))
-               return 0;
-
-       /* out_alt */
-       if (sctl & 0x00000400)
-               return 108000;
-
-       /* vco_out */
-       switch (sctl & 0x00003000) {
-       case 0x00000000:
-               if (!(sctl & 0x00000200))
-                       return nv_device(priv)->crystal;
-               return 0;
-       case 0x00002000:
-               if (sctl & 0x00000040)
-                       return 108000;
-               return 100000;
-       case 0x00003000:
-               /* vco_enable */
-               if (!(sctl & 0x00000001))
-                       return 0;
-
-               sclk = read_vco(priv, clk);
-               sdiv = ((sctl & 0x003f0000) >> 16) + 2;
-               return (sclk * 2) / sdiv;
-       default:
-               return 0;
-       }
-}
-
-static u32
-read_pll(struct nva3_clock_priv *priv, int clk, u32 pll)
-{
-       u32 ctrl = nv_rd32(priv, pll + 0);
-       u32 sclk = 0, P = 1, N = 1, M = 1;
-
-       if (!(ctrl & 0x00000008)) {
-               if (ctrl & 0x00000001) {
-                       u32 coef = nv_rd32(priv, pll + 4);
-                       M = (coef & 0x000000ff) >> 0;
-                       N = (coef & 0x0000ff00) >> 8;
-                       P = (coef & 0x003f0000) >> 16;
-
-                       /* no post-divider on these..
-                        * XXX: it looks more like two post-"dividers" that
-                        * cross each other out in the default RPLL config */
-                       if ((pll & 0x00ff00) == 0x00e800)
-                               P = 1;
-
-                       sclk = read_clk(priv, 0x00 + clk, false);
-               }
-       } else {
-               sclk = read_clk(priv, 0x10 + clk, false);
-       }
-
-       if (M * P)
-               return sclk * N / (M * P);
-       return 0;
-}
-
-static int
-nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct nva3_clock_priv *priv = (void *)clk;
-       u32 hsrc;
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return nv_device(priv)->crystal;
-       case nv_clk_src_core:
-       case nv_clk_src_core_intm:
-               return read_pll(priv, 0x00, 0x4200);
-       case nv_clk_src_shader:
-               return read_pll(priv, 0x01, 0x4220);
-       case nv_clk_src_mem:
-               return read_pll(priv, 0x02, 0x4000);
-       case nv_clk_src_disp:
-               return read_clk(priv, 0x20, false);
-       case nv_clk_src_vdec:
-               return read_clk(priv, 0x21, false);
-       case nv_clk_src_daemon:
-               return read_clk(priv, 0x25, false);
-       case nv_clk_src_host:
-               hsrc = (nv_rd32(priv, 0xc040) & 0x30000000) >> 28;
-               switch (hsrc) {
-               case 0:
-                       return read_clk(priv, 0x1d, false);
-               case 2:
-               case 3:
-                       return 277000;
-               default:
-                       nv_error(clk, "unknown HOST clock source %d\n", hsrc);
-                       return -EINVAL;
-               }
-       default:
-               nv_error(clk, "invalid clock source %d\n", src);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int
-nva3_clk_info(struct nouveau_clock *clock, int clk, u32 khz,
-               struct nva3_clock_info *info)
-{
-       struct nva3_clock_priv *priv = (void *)clock;
-       u32 oclk, sclk, sdiv, diff;
-
-       info->clk = 0;
-
-       switch (khz) {
-       case 27000:
-               info->clk = 0x00000100;
-               return khz;
-       case 100000:
-               info->clk = 0x00002100;
-               return khz;
-       case 108000:
-               info->clk = 0x00002140;
-               return khz;
-       default:
-               sclk = read_vco(priv, clk);
-               sdiv = min((sclk * 2) / khz, (u32)65);
-               oclk = (sclk * 2) / sdiv;
-               diff = ((khz + 3000) - oclk);
-
-               /* When imprecise, play it safe and aim for a clock lower than
-                * desired rather than higher */
-               if (diff < 0) {
-                       sdiv++;
-                       oclk = (sclk * 2) / sdiv;
-               }
-
-               /* divider can go as low as 2, limited here because NVIDIA
-                * and the VBIOS on my NVA8 seem to prefer using the PLL
-                * for 810MHz - is there a good reason?
-                * XXX: PLLs with refclk 810MHz?  */
-               if (sdiv > 4) {
-                       info->clk = (((sdiv - 2) << 16) | 0x00003100);
-                       return oclk;
-               }
-
-               break;
-       }
-
-       return -ERANGE;
-}
-
-int
-nva3_pll_info(struct nouveau_clock *clock, int clk, u32 pll, u32 khz,
-               struct nva3_clock_info *info)
-{
-       struct nouveau_bios *bios = nouveau_bios(clock);
-       struct nva3_clock_priv *priv = (void *)clock;
-       struct nvbios_pll limits;
-       int P, N, M, diff;
-       int ret;
-
-       info->pll = 0;
-
-       /* If we can get a within [-2, 3) MHz of a divider, we'll disable the
-        * PLL and use the divider instead. */
-       ret = nva3_clk_info(clock, clk, khz, info);
-       diff = khz - ret;
-       if (!pll || (diff >= -2000 && diff < 3000)) {
-               goto out;
-       }
-
-       /* Try with PLL */
-       ret = nvbios_pll_parse(bios, pll, &limits);
-       if (ret)
-               return ret;
-
-       ret = nva3_clk_info(clock, clk - 0x10, limits.refclk, info);
-       if (ret != limits.refclk)
-               return -EINVAL;
-
-       ret = nva3_pll_calc(nv_subdev(priv), &limits, khz, &N, NULL, &M, &P);
-       if (ret >= 0) {
-               info->pll = (P << 16) | (N << 8) | M;
-       }
-
-out:
-       info->fb_delay = max(((khz + 7566) / 15133), (u32) 18);
-
-       return ret ? ret : -ERANGE;
-}
-
-static int
-calc_clk(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate,
-        int clk, u32 pll, int idx)
-{
-       int ret = nva3_pll_info(&priv->base, clk, pll, cstate->domain[idx],
-                                 &priv->eng[idx]);
-       if (ret >= 0)
-               return 0;
-       return ret;
-}
-
-static int
-calc_host(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate)
-{
-       int ret = 0;
-       u32 kHz = cstate->domain[nv_clk_src_host];
-       struct nva3_clock_info *info = &priv->eng[nv_clk_src_host];
-
-       if (kHz == 277000) {
-               info->clk = 0;
-               info->host_out = NVA3_HOST_277;
-               return 0;
-       }
-
-       info->host_out = NVA3_HOST_CLK;
-
-       ret = nva3_clk_info(&priv->base, 0x1d, kHz, info);
-       if (ret >= 0)
-               return 0;
-       return ret;
-}
-
-int
-nva3_clock_pre(struct nouveau_clock *clk, unsigned long *flags)
-{
-       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
-
-       /* halt and idle execution engines */
-       nv_mask(clk, 0x020060, 0x00070000, 0x00000000);
-       nv_mask(clk, 0x002504, 0x00000001, 0x00000001);
-       /* Wait until the interrupt handler is finished */
-       if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000))
-               return -EBUSY;
-
-       if (pfifo)
-               pfifo->pause(pfifo, flags);
-
-       if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010))
-               return -EIO;
-       if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f))
-               return -EIO;
-
-       return 0;
-}
-
-void
-nva3_clock_post(struct nouveau_clock *clk, unsigned long *flags)
-{
-       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
-
-       if (pfifo && flags)
-               pfifo->start(pfifo, flags);
-
-       nv_mask(clk, 0x002504, 0x00000001, 0x00000000);
-       nv_mask(clk, 0x020060, 0x00070000, 0x00040000);
-}
-
-static void
-disable_clk_src(struct nva3_clock_priv *priv, u32 src)
-{
-       nv_mask(priv, src, 0x00000100, 0x00000000);
-       nv_mask(priv, src, 0x00000001, 0x00000000);
-}
-
-static void
-prog_pll(struct nva3_clock_priv *priv, int clk, u32 pll, int idx)
-{
-       struct nva3_clock_info *info = &priv->eng[idx];
-       const u32 src0 = 0x004120 + (clk * 4);
-       const u32 src1 = 0x004160 + (clk * 4);
-       const u32 ctrl = pll + 0;
-       const u32 coef = pll + 4;
-       u32 bypass;
-
-       if (info->pll) {
-               /* Always start from a non-PLL clock */
-               bypass = nv_rd32(priv, ctrl)  & 0x00000008;
-               if (!bypass) {
-                       nv_mask(priv, src1, 0x00000101, 0x00000101);
-                       nv_mask(priv, ctrl, 0x00000008, 0x00000008);
-                       udelay(20);
-               }
-
-               nv_mask(priv, src0, 0x003f3141, 0x00000101 | info->clk);
-               nv_wr32(priv, coef, info->pll);
-               nv_mask(priv, ctrl, 0x00000015, 0x00000015);
-               nv_mask(priv, ctrl, 0x00000010, 0x00000000);
-               if (!nv_wait(priv, ctrl, 0x00020000, 0x00020000)) {
-                       nv_mask(priv, ctrl, 0x00000010, 0x00000010);
-                       nv_mask(priv, src0, 0x00000101, 0x00000000);
-                       return;
-               }
-               nv_mask(priv, ctrl, 0x00000010, 0x00000010);
-               nv_mask(priv, ctrl, 0x00000008, 0x00000000);
-               disable_clk_src(priv, src1);
-       } else {
-               nv_mask(priv, src1, 0x003f3141, 0x00000101 | info->clk);
-               nv_mask(priv, ctrl, 0x00000018, 0x00000018);
-               udelay(20);
-               nv_mask(priv, ctrl, 0x00000001, 0x00000000);
-               disable_clk_src(priv, src0);
-       }
-}
-
-static void
-prog_clk(struct nva3_clock_priv *priv, int clk, int idx)
-{
-       struct nva3_clock_info *info = &priv->eng[idx];
-       nv_mask(priv, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | info->clk);
-}
-
-static void
-prog_host(struct nva3_clock_priv *priv)
-{
-       struct nva3_clock_info *info = &priv->eng[nv_clk_src_host];
-       u32 hsrc = (nv_rd32(priv, 0xc040));
-
-       switch (info->host_out) {
-       case NVA3_HOST_277:
-               if ((hsrc & 0x30000000) == 0) {
-                       nv_wr32(priv, 0xc040, hsrc | 0x20000000);
-                       disable_clk_src(priv, 0x4194);
-               }
-               break;
-       case NVA3_HOST_CLK:
-               prog_clk(priv, 0x1d, nv_clk_src_host);
-               if ((hsrc & 0x30000000) >= 0x20000000) {
-                       nv_wr32(priv, 0xc040, hsrc & ~0x30000000);
-               }
-               break;
-       default:
-               break;
-       }
-
-       /* This seems to be a clock gating factor on idle, always set to 64 */
-       nv_wr32(priv, 0xc044, 0x3e);
-}
-
-static void
-prog_core(struct nva3_clock_priv *priv, int idx)
-{
-       struct nva3_clock_info *info = &priv->eng[idx];
-       u32 fb_delay = nv_rd32(priv, 0x10002c);
-
-       if (fb_delay < info->fb_delay)
-               nv_wr32(priv, 0x10002c, info->fb_delay);
-
-       prog_pll(priv, 0x00, 0x004200, idx);
-
-       if (fb_delay > info->fb_delay)
-               nv_wr32(priv, 0x10002c, info->fb_delay);
-}
-
-static int
-nva3_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct nva3_clock_priv *priv = (void *)clk;
-       struct nva3_clock_info *core = &priv->eng[nv_clk_src_core];
-       int ret;
-
-       if ((ret = calc_clk(priv, cstate, 0x10, 0x4200, nv_clk_src_core)) ||
-           (ret = calc_clk(priv, cstate, 0x11, 0x4220, nv_clk_src_shader)) ||
-           (ret = calc_clk(priv, cstate, 0x20, 0x0000, nv_clk_src_disp)) ||
-           (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec)) ||
-           (ret = calc_host(priv, cstate)))
-               return ret;
-
-       /* XXX: Should be reading the highest bit in the VBIOS clock to decide
-        * whether to use a PLL or not... but using a PLL defeats the purpose */
-       if (core->pll) {
-               ret = nva3_clk_info(clk, 0x10,
-                               cstate->domain[nv_clk_src_core_intm],
-                               &priv->eng[nv_clk_src_core_intm]);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int
-nva3_clock_prog(struct nouveau_clock *clk)
-{
-       struct nva3_clock_priv *priv = (void *)clk;
-       struct nva3_clock_info *core = &priv->eng[nv_clk_src_core];
-       int ret = 0;
-       unsigned long flags;
-       unsigned long *f = &flags;
-
-       ret = nva3_clock_pre(clk, f);
-       if (ret)
-               goto out;
-
-       if (core->pll)
-               prog_core(priv, nv_clk_src_core_intm);
-
-       prog_core(priv,  nv_clk_src_core);
-       prog_pll(priv, 0x01, 0x004220, nv_clk_src_shader);
-       prog_clk(priv, 0x20, nv_clk_src_disp);
-       prog_clk(priv, 0x21, nv_clk_src_vdec);
-       prog_host(priv);
-
-out:
-       if (ret == -EBUSY)
-               f = NULL;
-
-       nva3_clock_post(clk, f);
-
-       return ret;
-}
-
-static void
-nva3_clock_tidy(struct nouveau_clock *clk)
-{
-}
-
-static struct nouveau_clocks
-nva3_domain[] = {
-       { nv_clk_src_crystal  , 0xff },
-       { nv_clk_src_core     , 0x00, 0, "core", 1000 },
-       { nv_clk_src_shader   , 0x01, 0, "shader", 1000 },
-       { nv_clk_src_mem      , 0x02, 0, "memory", 1000 },
-       { nv_clk_src_vdec     , 0x03 },
-       { nv_clk_src_disp     , 0x04 },
-       { nv_clk_src_host     , 0x05 },
-       { nv_clk_src_core_intm, 0x06 },
-       { nv_clk_src_max }
-};
-
-static int
-nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nva3_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, NULL, 0,
-                                  true, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.read = nva3_clock_read;
-       priv->base.calc = nva3_clock_calc;
-       priv->base.prog = nva3_clock_prog;
-       priv->base.tidy = nva3_clock_tidy;
-       return 0;
-}
-
-struct nouveau_oclass
-nva3_clock_oclass = {
-       .handle = NV_SUBDEV(CLOCK, 0xa3),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nva3_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nva3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nva3.h
deleted file mode 100644 (file)
index a45a103..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __NVKM_CLK_NVA3_H__
-#define __NVKM_CLK_NVA3_H__
-
-#include <subdev/clock.h>
-
-struct nva3_clock_info {
-       u32 clk;
-       u32 pll;
-       enum {
-               NVA3_HOST_277,
-               NVA3_HOST_CLK,
-       } host_out;
-       u32 fb_delay;
-};
-
-int nva3_pll_info(struct nouveau_clock *, int, u32, u32,
-                   struct nva3_clock_info *);
-int nva3_clock_pre(struct nouveau_clock *clk, unsigned long *flags);
-void nva3_clock_post(struct nouveau_clock *clk, unsigned long *flags);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nvaa.c
deleted file mode 100644 (file)
index 54aeab8..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <engine/fifo.h>
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-#include <subdev/timer.h>
-#include <subdev/clock.h>
-
-#include "nva3.h"
-#include "pll.h"
-
-struct nvaa_clock_priv {
-       struct nouveau_clock base;
-       enum nv_clk_src csrc, ssrc, vsrc;
-       u32 cctrl, sctrl;
-       u32 ccoef, scoef;
-       u32 cpost, spost;
-       u32 vdiv;
-};
-
-static u32
-read_div(struct nouveau_clock *clk)
-{
-       return nv_rd32(clk, 0x004600);
-}
-
-static u32
-read_pll(struct nouveau_clock *clk, u32 base)
-{
-       u32 ctrl = nv_rd32(clk, base + 0);
-       u32 coef = nv_rd32(clk, base + 4);
-       u32 ref = clk->read(clk, nv_clk_src_href);
-       u32 post_div = 0;
-       u32 clock = 0;
-       int N1, M1;
-
-       switch (base){
-       case 0x4020:
-               post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16);
-               break;
-       case 0x4028:
-               post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16;
-               break;
-       default:
-               break;
-       }
-
-       N1 = (coef & 0x0000ff00) >> 8;
-       M1 = (coef & 0x000000ff);
-       if ((ctrl & 0x80000000) && M1) {
-               clock = ref * N1 / M1;
-               clock = clock / post_div;
-       }
-
-       return clock;
-}
-
-static int
-nvaa_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct nvaa_clock_priv *priv = (void *)clk;
-       u32 mast = nv_rd32(clk, 0x00c054);
-       u32 P = 0;
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return nv_device(priv)->crystal;
-       case nv_clk_src_href:
-               return 100000; /* PCIE reference clock */
-       case nv_clk_src_hclkm4:
-               return clk->read(clk, nv_clk_src_href) * 4;
-       case nv_clk_src_hclkm2d3:
-               return clk->read(clk, nv_clk_src_href) * 2 / 3;
-       case nv_clk_src_host:
-               switch (mast & 0x000c0000) {
-               case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3);
-               case 0x00040000: break;
-               case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4);
-               case 0x000c0000: return clk->read(clk, nv_clk_src_cclk);
-               }
-               break;
-       case nv_clk_src_core:
-               P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16;
-
-               switch (mast & 0x00000003) {
-               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
-               case 0x00000001: return 0;
-               case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P;
-               case 0x00000003: return read_pll(clk, 0x004028) >> P;
-               }
-               break;
-       case nv_clk_src_cclk:
-               if ((mast & 0x03000000) != 0x03000000)
-                       return clk->read(clk, nv_clk_src_core);
-
-               if ((mast & 0x00000200) == 0x00000000)
-                       return clk->read(clk, nv_clk_src_core);
-
-               switch (mast & 0x00000c00) {
-               case 0x00000000: return clk->read(clk, nv_clk_src_href);
-               case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4);
-               case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3);
-               default: return 0;
-               }
-       case nv_clk_src_shader:
-               P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16;
-               switch (mast & 0x00000030) {
-               case 0x00000000:
-                       if (mast & 0x00000040)
-                               return clk->read(clk, nv_clk_src_href) >> P;
-                       return clk->read(clk, nv_clk_src_crystal) >> P;
-               case 0x00000010: break;
-               case 0x00000020: return read_pll(clk, 0x004028) >> P;
-               case 0x00000030: return read_pll(clk, 0x004020) >> P;
-               }
-               break;
-       case nv_clk_src_mem:
-               return 0;
-               break;
-       case nv_clk_src_vdec:
-               P = (read_div(clk) & 0x00000700) >> 8;
-
-               switch (mast & 0x00400000) {
-               case 0x00400000:
-                       return clk->read(clk, nv_clk_src_core) >> P;
-                       break;
-               default:
-                       return 500000 >> P;
-                       break;
-               }
-               break;
-       default:
-               break;
-       }
-
-       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
-       return 0;
-}
-
-static u32
-calc_pll(struct nvaa_clock_priv *priv, u32 reg,
-        u32 clock, int *N, int *M, int *P)
-{
-       struct nouveau_bios *bios = nouveau_bios(priv);
-       struct nvbios_pll pll;
-       struct nouveau_clock *clk = &priv->base;
-       int ret;
-
-       ret = nvbios_pll_parse(bios, reg, &pll);
-       if (ret)
-               return 0;
-
-       pll.vco2.max_freq = 0;
-       pll.refclk = clk->read(clk, nv_clk_src_href);
-       if (!pll.refclk)
-               return 0;
-
-       return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P);
-}
-
-static inline u32
-calc_P(u32 src, u32 target, int *div)
-{
-       u32 clk0 = src, clk1 = src;
-       for (*div = 0; *div <= 7; (*div)++) {
-               if (clk0 <= target) {
-                       clk1 = clk0 << (*div ? 1 : 0);
-                       break;
-               }
-               clk0 >>= 1;
-       }
-
-       if (target - clk0 <= clk1 - target)
-               return clk0;
-       (*div)--;
-       return clk1;
-}
-
-static int
-nvaa_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct nvaa_clock_priv *priv = (void *)clk;
-       const int shader = cstate->domain[nv_clk_src_shader];
-       const int core = cstate->domain[nv_clk_src_core];
-       const int vdec = cstate->domain[nv_clk_src_vdec];
-       u32 out = 0, clock = 0;
-       int N, M, P1, P2 = 0;
-       int divs = 0;
-
-       /* cclk: find suitable source, disable PLL if we can */
-       if (core < clk->read(clk, nv_clk_src_hclkm4))
-               out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs);
-
-       /* Calculate clock * 2, so shader clock can use it too */
-       clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1);
-
-       if (abs(core - out) <=
-           abs(core - (clock >> 1))) {
-               priv->csrc = nv_clk_src_hclkm4;
-               priv->cctrl = divs << 16;
-       } else {
-               /* NVCTRL is actually used _after_ NVPOST, and after what we
-                * call NVPLL. To make matters worse, NVPOST is an integer
-                * divider instead of a right-shift number. */
-               if(P1 > 2) {
-                       P2 = P1 - 2;
-                       P1 = 2;
-               }
-
-               priv->csrc = nv_clk_src_core;
-               priv->ccoef = (N << 8) | M;
-
-               priv->cctrl = (P2 + 1) << 16;
-               priv->cpost = (1 << P1) << 16;
-       }
-
-       /* sclk: nvpll + divisor, href or spll */
-       out = 0;
-       if (shader == clk->read(clk, nv_clk_src_href)) {
-               priv->ssrc = nv_clk_src_href;
-       } else {
-               clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
-               if (priv->csrc == nv_clk_src_core) {
-                       out = calc_P((core << 1), shader, &divs);
-               }
-
-               if (abs(shader - out) <=
-                   abs(shader - clock) &&
-                  (divs + P2) <= 7) {
-                       priv->ssrc = nv_clk_src_core;
-                       priv->sctrl = (divs + P2) << 16;
-               } else {
-                       priv->ssrc = nv_clk_src_shader;
-                       priv->scoef = (N << 8) | M;
-                       priv->sctrl = P1 << 16;
-               }
-       }
-
-       /* vclk */
-       out = calc_P(core, vdec, &divs);
-       clock = calc_P(500000, vdec, &P1);
-       if(abs(vdec - out) <=
-          abs(vdec - clock)) {
-               priv->vsrc = nv_clk_src_cclk;
-               priv->vdiv = divs << 16;
-       } else {
-               priv->vsrc = nv_clk_src_vdec;
-               priv->vdiv = P1 << 16;
-       }
-
-       /* Print strategy! */
-       nv_debug(priv, "nvpll: %08x %08x %08x\n",
-                       priv->ccoef, priv->cpost, priv->cctrl);
-       nv_debug(priv, " spll: %08x %08x %08x\n",
-                       priv->scoef, priv->spost, priv->sctrl);
-       nv_debug(priv, " vdiv: %08x\n", priv->vdiv);
-       if (priv->csrc == nv_clk_src_hclkm4)
-               nv_debug(priv, "core: hrefm4\n");
-       else
-               nv_debug(priv, "core: nvpll\n");
-
-       if (priv->ssrc == nv_clk_src_hclkm4)
-               nv_debug(priv, "shader: hrefm4\n");
-       else if (priv->ssrc == nv_clk_src_core)
-               nv_debug(priv, "shader: nvpll\n");
-       else
-               nv_debug(priv, "shader: spll\n");
-
-       if (priv->vsrc == nv_clk_src_hclkm4)
-               nv_debug(priv, "vdec: 500MHz\n");
-       else
-               nv_debug(priv, "vdec: core\n");
-
-       return 0;
-}
-
-static int
-nvaa_clock_prog(struct nouveau_clock *clk)
-{
-       struct nvaa_clock_priv *priv = (void *)clk;
-       u32 pllmask = 0, mast;
-       unsigned long flags;
-       unsigned long *f = &flags;
-       int ret = 0;
-
-       ret = nva3_clock_pre(clk, f);
-       if (ret)
-               goto out;
-
-       /* First switch to safe clocks: href */
-       mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640);
-       mast &= ~0x00400e73;
-       mast |= 0x03000000;
-
-       switch (priv->csrc) {
-       case nv_clk_src_hclkm4:
-               nv_mask(clk, 0x4028, 0x00070000, priv->cctrl);
-               mast |= 0x00000002;
-               break;
-       case nv_clk_src_core:
-               nv_wr32(clk, 0x402c, priv->ccoef);
-               nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl);
-               nv_wr32(clk, 0x4040, priv->cpost);
-               pllmask |= (0x3 << 8);
-               mast |= 0x00000003;
-               break;
-       default:
-               nv_warn(priv,"Reclocking failed: unknown core clock\n");
-               goto resume;
-       }
-
-       switch (priv->ssrc) {
-       case nv_clk_src_href:
-               nv_mask(clk, 0x4020, 0x00070000, 0x00000000);
-               /* mast |= 0x00000000; */
-               break;
-       case nv_clk_src_core:
-               nv_mask(clk, 0x4020, 0x00070000, priv->sctrl);
-               mast |= 0x00000020;
-               break;
-       case nv_clk_src_shader:
-               nv_wr32(clk, 0x4024, priv->scoef);
-               nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl);
-               nv_wr32(clk, 0x4070, priv->spost);
-               pllmask |= (0x3 << 12);
-               mast |= 0x00000030;
-               break;
-       default:
-               nv_warn(priv,"Reclocking failed: unknown sclk clock\n");
-               goto resume;
-       }
-
-       if (!nv_wait(clk, 0x004080, pllmask, pllmask)) {
-               nv_warn(priv,"Reclocking failed: unstable PLLs\n");
-               goto resume;
-       }
-
-       switch (priv->vsrc) {
-       case nv_clk_src_cclk:
-               mast |= 0x00400000;
-       default:
-               nv_wr32(clk, 0x4600, priv->vdiv);
-       }
-
-       nv_wr32(clk, 0xc054, mast);
-
-resume:
-       /* Disable some PLLs and dividers when unused */
-       if (priv->csrc != nv_clk_src_core) {
-               nv_wr32(clk, 0x4040, 0x00000000);
-               nv_mask(clk, 0x4028, 0x80000000, 0x00000000);
-       }
-
-       if (priv->ssrc != nv_clk_src_shader) {
-               nv_wr32(clk, 0x4070, 0x00000000);
-               nv_mask(clk, 0x4020, 0x80000000, 0x00000000);
-       }
-
-out:
-       if (ret == -EBUSY)
-               f = NULL;
-
-       nva3_clock_post(clk, f);
-
-       return ret;
-}
-
-static void
-nvaa_clock_tidy(struct nouveau_clock *clk)
-{
-}
-
-static struct nouveau_clocks
-nvaa_domains[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_href   , 0xff },
-       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
-       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
-       { nv_clk_src_vdec   , 0xff, 0, "vdec", 1000 },
-       { nv_clk_src_max }
-};
-
-static int
-nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nvaa_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, NULL,
-                                  0, true, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.read = nvaa_clock_read;
-       priv->base.calc = nvaa_clock_calc;
-       priv->base.prog = nvaa_clock_prog;
-       priv->base.tidy = nvaa_clock_tidy;
-       return 0;
-}
-
-struct nouveau_oclass *
-nvaa_clock_oclass = &(struct nouveau_oclass) {
-       .handle = NV_SUBDEV(CLOCK, 0xaa),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nvaa_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nvc0.c
deleted file mode 100644 (file)
index 1234aba..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/clock.h>
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-#include <subdev/timer.h>
-
-#include "pll.h"
-
-struct nvc0_clock_info {
-       u32 freq;
-       u32 ssel;
-       u32 mdiv;
-       u32 dsrc;
-       u32 ddiv;
-       u32 coef;
-};
-
-struct nvc0_clock_priv {
-       struct nouveau_clock base;
-       struct nvc0_clock_info eng[16];
-};
-
-static u32 read_div(struct nvc0_clock_priv *, int, u32, u32);
-
-static u32
-read_vco(struct nvc0_clock_priv *priv, u32 dsrc)
-{
-       struct nouveau_clock *clk = &priv->base;
-       u32 ssrc = nv_rd32(priv, dsrc);
-       if (!(ssrc & 0x00000100))
-               return clk->read(clk, nv_clk_src_sppll0);
-       return clk->read(clk, nv_clk_src_sppll1);
-}
-
-static u32
-read_pll(struct nvc0_clock_priv *priv, u32 pll)
-{
-       struct nouveau_clock *clk = &priv->base;
-       u32 ctrl = nv_rd32(priv, pll + 0x00);
-       u32 coef = nv_rd32(priv, pll + 0x04);
-       u32 P = (coef & 0x003f0000) >> 16;
-       u32 N = (coef & 0x0000ff00) >> 8;
-       u32 M = (coef & 0x000000ff) >> 0;
-       u32 sclk;
-
-       if (!(ctrl & 0x00000001))
-               return 0;
-
-       switch (pll) {
-       case 0x00e800:
-       case 0x00e820:
-               sclk = nv_device(priv)->crystal;
-               P = 1;
-               break;
-       case 0x132000:
-               sclk = clk->read(clk, nv_clk_src_mpllsrc);
-               break;
-       case 0x132020:
-               sclk = clk->read(clk, nv_clk_src_mpllsrcref);
-               break;
-       case 0x137000:
-       case 0x137020:
-       case 0x137040:
-       case 0x1370e0:
-               sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140);
-               break;
-       default:
-               return 0;
-       }
-
-       return sclk * N / M / P;
-}
-
-static u32
-read_div(struct nvc0_clock_priv *priv, int doff, u32 dsrc, u32 dctl)
-{
-       u32 ssrc = nv_rd32(priv, dsrc + (doff * 4));
-       u32 sctl = nv_rd32(priv, dctl + (doff * 4));
-
-       switch (ssrc & 0x00000003) {
-       case 0:
-               if ((ssrc & 0x00030000) != 0x00030000)
-                       return nv_device(priv)->crystal;
-               return 108000;
-       case 2:
-               return 100000;
-       case 3:
-               if (sctl & 0x80000000) {
-                       u32 sclk = read_vco(priv, dsrc + (doff * 4));
-                       u32 sdiv = (sctl & 0x0000003f) + 2;
-                       return (sclk * 2) / sdiv;
-               }
-
-               return read_vco(priv, dsrc + (doff * 4));
-       default:
-               return 0;
-       }
-}
-
-static u32
-read_clk(struct nvc0_clock_priv *priv, int clk)
-{
-       u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4));
-       u32 ssel = nv_rd32(priv, 0x137100);
-       u32 sclk, sdiv;
-
-       if (ssel & (1 << clk)) {
-               if (clk < 7)
-                       sclk = read_pll(priv, 0x137000 + (clk * 0x20));
-               else
-                       sclk = read_pll(priv, 0x1370e0);
-               sdiv = ((sctl & 0x00003f00) >> 8) + 2;
-       } else {
-               sclk = read_div(priv, clk, 0x137160, 0x1371d0);
-               sdiv = ((sctl & 0x0000003f) >> 0) + 2;
-       }
-
-       if (sctl & 0x80000000)
-               return (sclk * 2) / sdiv;
-
-       return sclk;
-}
-
-static int
-nvc0_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct nouveau_device *device = nv_device(clk);
-       struct nvc0_clock_priv *priv = (void *)clk;
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return device->crystal;
-       case nv_clk_src_href:
-               return 100000;
-       case nv_clk_src_sppll0:
-               return read_pll(priv, 0x00e800);
-       case nv_clk_src_sppll1:
-               return read_pll(priv, 0x00e820);
-
-       case nv_clk_src_mpllsrcref:
-               return read_div(priv, 0, 0x137320, 0x137330);
-       case nv_clk_src_mpllsrc:
-               return read_pll(priv, 0x132020);
-       case nv_clk_src_mpll:
-               return read_pll(priv, 0x132000);
-       case nv_clk_src_mdiv:
-               return read_div(priv, 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);
-
-       case nv_clk_src_gpc:
-               return read_clk(priv, 0x00);
-       case nv_clk_src_rop:
-               return read_clk(priv, 0x01);
-       case nv_clk_src_hubk07:
-               return read_clk(priv, 0x02);
-       case nv_clk_src_hubk06:
-               return read_clk(priv, 0x07);
-       case nv_clk_src_hubk01:
-               return read_clk(priv, 0x08);
-       case nv_clk_src_copy:
-               return read_clk(priv, 0x09);
-       case nv_clk_src_daemon:
-               return read_clk(priv, 0x0c);
-       case nv_clk_src_vdec:
-               return read_clk(priv, 0x0e);
-       default:
-               nv_error(clk, "invalid clock source %d\n", src);
-               return -EINVAL;
-       }
-}
-
-static u32
-calc_div(struct nvc0_clock_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv)
-{
-       u32 div = min((ref * 2) / freq, (u32)65);
-       if (div < 2)
-               div = 2;
-
-       *ddiv = div - 2;
-       return (ref * 2) / div;
-}
-
-static u32
-calc_src(struct nvc0_clock_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
-{
-       u32 sclk;
-
-       /* use one of the fixed frequencies if possible */
-       *ddiv = 0x00000000;
-       switch (freq) {
-       case  27000:
-       case 108000:
-               *dsrc = 0x00000000;
-               if (freq == 108000)
-                       *dsrc |= 0x00030000;
-               return freq;
-       case 100000:
-               *dsrc = 0x00000002;
-               return freq;
-       default:
-               *dsrc = 0x00000003;
-               break;
-       }
-
-       /* otherwise, calculate the closest divider */
-       sclk = read_vco(priv, 0x137160 + (clk * 4));
-       if (clk < 7)
-               sclk = calc_div(priv, clk, sclk, freq, ddiv);
-       return sclk;
-}
-
-static u32
-calc_pll(struct nvc0_clock_priv *priv, int clk, u32 freq, u32 *coef)
-{
-       struct nouveau_bios *bios = nouveau_bios(priv);
-       struct nvbios_pll limits;
-       int N, M, P, ret;
-
-       ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits);
-       if (ret)
-               return 0;
-
-       limits.refclk = read_div(priv, clk, 0x137120, 0x137140);
-       if (!limits.refclk)
-               return 0;
-
-       ret = nva3_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P);
-       if (ret <= 0)
-               return 0;
-
-       *coef = (P << 16) | (N << 8) | M;
-       return ret;
-}
-
-static int
-calc_clk(struct nvc0_clock_priv *priv,
-        struct nouveau_cstate *cstate, int clk, int dom)
-{
-       struct nvc0_clock_info *info = &priv->eng[clk];
-       u32 freq = cstate->domain[dom];
-       u32 src0, div0, div1D, div1P = 0;
-       u32 clk0, clk1 = 0;
-
-       /* invalid clock domain */
-       if (!freq)
-               return 0;
-
-       /* first possible path, using only dividers */
-       clk0 = calc_src(priv, clk, freq, &src0, &div0);
-       clk0 = calc_div(priv, clk, 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);
-               else
-                       clk1 = cstate->domain[nv_clk_src_hubk06];
-               clk1 = calc_div(priv, clk, clk1, freq, &div1P);
-       }
-
-       /* select the method which gets closest to target freq */
-       if (abs((int)freq - clk0) <= abs((int)freq - clk1)) {
-               info->dsrc = src0;
-               if (div0) {
-                       info->ddiv |= 0x80000000;
-                       info->ddiv |= div0 << 8;
-                       info->ddiv |= div0;
-               }
-               if (div1D) {
-                       info->mdiv |= 0x80000000;
-                       info->mdiv |= div1D;
-               }
-               info->ssel = info->coef = 0;
-               info->freq = clk0;
-       } else {
-               if (div1P) {
-                       info->mdiv |= 0x80000000;
-                       info->mdiv |= div1P << 8;
-               }
-               info->ssel = (1 << clk);
-               info->freq = clk1;
-       }
-
-       return 0;
-}
-
-static int
-nvc0_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct nvc0_clock_priv *priv = (void *)clk;
-       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)))
-               return ret;
-
-       return 0;
-}
-
-static void
-nvc0_clock_prog_0(struct nvc0_clock_priv *priv, int clk)
-{
-       struct nvc0_clock_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);
-       }
-}
-
-static void
-nvc0_clock_prog_1(struct nvc0_clock_priv *priv, int clk)
-{
-       nv_mask(priv, 0x137100, (1 << clk), 0x00000000);
-       nv_wait(priv, 0x137100, (1 << clk), 0x00000000);
-}
-
-static void
-nvc0_clock_prog_2(struct nvc0_clock_priv *priv, int clk)
-{
-       struct nvc0_clock_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);
-               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);
-               }
-       }
-}
-
-static void
-nvc0_clock_prog_3(struct nvc0_clock_priv *priv, int clk)
-{
-       struct nvc0_clock_info *info = &priv->eng[clk];
-       if (info->ssel) {
-               nv_mask(priv, 0x137100, (1 << clk), info->ssel);
-               nv_wait(priv, 0x137100, (1 << clk), info->ssel);
-       }
-}
-
-static void
-nvc0_clock_prog_4(struct nvc0_clock_priv *priv, int clk)
-{
-       struct nvc0_clock_info *info = &priv->eng[clk];
-       nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv);
-}
-
-static int
-nvc0_clock_prog(struct nouveau_clock *clk)
-{
-       struct nvc0_clock_priv *priv = (void *)clk;
-       struct {
-               void (*exec)(struct nvc0_clock_priv *, int);
-       } stage[] = {
-               { nvc0_clock_prog_0 }, /* div programming */
-               { nvc0_clock_prog_1 }, /* select div mode */
-               { nvc0_clock_prog_2 }, /* (maybe) program pll */
-               { nvc0_clock_prog_3 }, /* (maybe) select pll mode */
-               { nvc0_clock_prog_4 }, /* final divider */
-       };
-       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)
-                               continue;
-                       stage[i].exec(priv, j);
-               }
-       }
-
-       return 0;
-}
-
-static void
-nvc0_clock_tidy(struct nouveau_clock *clk)
-{
-       struct nvc0_clock_priv *priv = (void *)clk;
-       memset(priv->eng, 0x00, sizeof(priv->eng));
-}
-
-static struct nouveau_clocks
-nvc0_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 int
-nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nvc0_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, NULL, 0,
-                                  false, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.read = nvc0_clock_read;
-       priv->base.calc = nvc0_clock_calc;
-       priv->base.prog = nvc0_clock_prog;
-       priv->base.tidy = nvc0_clock_tidy;
-       return 0;
-}
-
-struct nouveau_oclass
-nvc0_clock_oclass = {
-       .handle = NV_SUBDEV(CLOCK, 0xc0),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nvc0_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nve0.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/nve0.c
deleted file mode 100644 (file)
index 7eccad5..0000000
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright 2013 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/clock.h>
-#include <subdev/timer.h>
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-
-#include "pll.h"
-
-struct nve0_clock_info {
-       u32 freq;
-       u32 ssel;
-       u32 mdiv;
-       u32 dsrc;
-       u32 ddiv;
-       u32 coef;
-};
-
-struct nve0_clock_priv {
-       struct nouveau_clock base;
-       struct nve0_clock_info eng[16];
-};
-
-static u32 read_div(struct nve0_clock_priv *, int, u32, u32);
-static u32 read_pll(struct nve0_clock_priv *, u32);
-
-static u32
-read_vco(struct nve0_clock_priv *priv, u32 dsrc)
-{
-       u32 ssrc = nv_rd32(priv, dsrc);
-       if (!(ssrc & 0x00000100))
-               return read_pll(priv, 0x00e800);
-       return read_pll(priv, 0x00e820);
-}
-
-static u32
-read_pll(struct nve0_clock_priv *priv, u32 pll)
-{
-       u32 ctrl = nv_rd32(priv, pll + 0x00);
-       u32 coef = nv_rd32(priv, pll + 0x04);
-       u32 P = (coef & 0x003f0000) >> 16;
-       u32 N = (coef & 0x0000ff00) >> 8;
-       u32 M = (coef & 0x000000ff) >> 0;
-       u32 sclk;
-       u16 fN = 0xf000;
-
-       if (!(ctrl & 0x00000001))
-               return 0;
-
-       switch (pll) {
-       case 0x00e800:
-       case 0x00e820:
-               sclk = nv_device(priv)->crystal;
-               P = 1;
-               break;
-       case 0x132000:
-               sclk = read_pll(priv, 0x132020);
-               P = (coef & 0x10000000) ? 2 : 1;
-               break;
-       case 0x132020:
-               sclk = read_div(priv, 0, 0x137320, 0x137330);
-               fN   = nv_rd32(priv, pll + 0x10) >> 16;
-               break;
-       case 0x137000:
-       case 0x137020:
-       case 0x137040:
-       case 0x1370e0:
-               sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140);
-               break;
-       default:
-               return 0;
-       }
-
-       if (P == 0)
-               P = 1;
-
-       sclk = (sclk * N) + (((u16)(fN + 4096) * sclk) >> 13);
-       return sclk / (M * P);
-}
-
-static u32
-read_div(struct nve0_clock_priv *priv, int doff, u32 dsrc, u32 dctl)
-{
-       u32 ssrc = nv_rd32(priv, dsrc + (doff * 4));
-       u32 sctl = nv_rd32(priv, dctl + (doff * 4));
-
-       switch (ssrc & 0x00000003) {
-       case 0:
-               if ((ssrc & 0x00030000) != 0x00030000)
-                       return nv_device(priv)->crystal;
-               return 108000;
-       case 2:
-               return 100000;
-       case 3:
-               if (sctl & 0x80000000) {
-                       u32 sclk = read_vco(priv, dsrc + (doff * 4));
-                       u32 sdiv = (sctl & 0x0000003f) + 2;
-                       return (sclk * 2) / sdiv;
-               }
-
-               return read_vco(priv, dsrc + (doff * 4));
-       default:
-               return 0;
-       }
-}
-
-static u32
-read_mem(struct nve0_clock_priv *priv)
-{
-       switch (nv_rd32(priv, 0x1373f4) & 0x0000000f) {
-       case 1: return read_pll(priv, 0x132020);
-       case 2: return read_pll(priv, 0x132000);
-       default:
-               return 0;
-       }
-}
-
-static u32
-read_clk(struct nve0_clock_priv *priv, int clk)
-{
-       u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4));
-       u32 sclk, sdiv;
-
-       if (clk < 7) {
-               u32 ssel = nv_rd32(priv, 0x137100);
-               if (ssel & (1 << clk)) {
-                       sclk = read_pll(priv, 0x137000 + (clk * 0x20));
-                       sdiv = 1;
-               } else {
-                       sclk = read_div(priv, clk, 0x137160, 0x1371d0);
-                       sdiv = 0;
-               }
-       } else {
-               u32 ssrc = nv_rd32(priv, 0x137160 + (clk * 0x04));
-               if ((ssrc & 0x00000003) == 0x00000003) {
-                       sclk = read_div(priv, clk, 0x137160, 0x1371d0);
-                       if (ssrc & 0x00000100) {
-                               if (ssrc & 0x40000000)
-                                       sclk = read_pll(priv, 0x1370e0);
-                               sdiv = 1;
-                       } else {
-                               sdiv = 0;
-                       }
-               } else {
-                       sclk = read_div(priv, clk, 0x137160, 0x1371d0);
-                       sdiv = 0;
-               }
-       }
-
-       if (sctl & 0x80000000) {
-               if (sdiv)
-                       sdiv = ((sctl & 0x00003f00) >> 8) + 2;
-               else
-                       sdiv = ((sctl & 0x0000003f) >> 0) + 2;
-               return (sclk * 2) / sdiv;
-       }
-
-       return sclk;
-}
-
-static int
-nve0_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
-{
-       struct nouveau_device *device = nv_device(clk);
-       struct nve0_clock_priv *priv = (void *)clk;
-
-       switch (src) {
-       case nv_clk_src_crystal:
-               return device->crystal;
-       case nv_clk_src_href:
-               return 100000;
-       case nv_clk_src_mem:
-               return read_mem(priv);
-       case nv_clk_src_gpc:
-               return read_clk(priv, 0x00);
-       case nv_clk_src_rop:
-               return read_clk(priv, 0x01);
-       case nv_clk_src_hubk07:
-               return read_clk(priv, 0x02);
-       case nv_clk_src_hubk06:
-               return read_clk(priv, 0x07);
-       case nv_clk_src_hubk01:
-               return read_clk(priv, 0x08);
-       case nv_clk_src_daemon:
-               return read_clk(priv, 0x0c);
-       case nv_clk_src_vdec:
-               return read_clk(priv, 0x0e);
-       default:
-               nv_error(clk, "invalid clock source %d\n", src);
-               return -EINVAL;
-       }
-}
-
-static u32
-calc_div(struct nve0_clock_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv)
-{
-       u32 div = min((ref * 2) / freq, (u32)65);
-       if (div < 2)
-               div = 2;
-
-       *ddiv = div - 2;
-       return (ref * 2) / div;
-}
-
-static u32
-calc_src(struct nve0_clock_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
-{
-       u32 sclk;
-
-       /* use one of the fixed frequencies if possible */
-       *ddiv = 0x00000000;
-       switch (freq) {
-       case  27000:
-       case 108000:
-               *dsrc = 0x00000000;
-               if (freq == 108000)
-                       *dsrc |= 0x00030000;
-               return freq;
-       case 100000:
-               *dsrc = 0x00000002;
-               return freq;
-       default:
-               *dsrc = 0x00000003;
-               break;
-       }
-
-       /* otherwise, calculate the closest divider */
-       sclk = read_vco(priv, 0x137160 + (clk * 4));
-       if (clk < 7)
-               sclk = calc_div(priv, clk, sclk, freq, ddiv);
-       return sclk;
-}
-
-static u32
-calc_pll(struct nve0_clock_priv *priv, int clk, u32 freq, u32 *coef)
-{
-       struct nouveau_bios *bios = nouveau_bios(priv);
-       struct nvbios_pll limits;
-       int N, M, P, ret;
-
-       ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits);
-       if (ret)
-               return 0;
-
-       limits.refclk = read_div(priv, clk, 0x137120, 0x137140);
-       if (!limits.refclk)
-               return 0;
-
-       ret = nva3_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P);
-       if (ret <= 0)
-               return 0;
-
-       *coef = (P << 16) | (N << 8) | M;
-       return ret;
-}
-
-static int
-calc_clk(struct nve0_clock_priv *priv,
-        struct nouveau_cstate *cstate, int clk, int dom)
-{
-       struct nve0_clock_info *info = &priv->eng[clk];
-       u32 freq = cstate->domain[dom];
-       u32 src0, div0, div1D, div1P = 0;
-       u32 clk0, clk1 = 0;
-
-       /* invalid clock domain */
-       if (!freq)
-               return 0;
-
-       /* first possible path, using only dividers */
-       clk0 = calc_src(priv, clk, freq, &src0, &div0);
-       clk0 = calc_div(priv, clk, clk0, freq, &div1D);
-
-       /* see if we can get any closer using PLLs */
-       if (clk0 != freq && (0x0000ff87 & (1 << clk))) {
-               if (clk <= 7)
-                       clk1 = calc_pll(priv, clk, freq, &info->coef);
-               else
-                       clk1 = cstate->domain[nv_clk_src_hubk06];
-               clk1 = calc_div(priv, clk, clk1, freq, &div1P);
-       }
-
-       /* select the method which gets closest to target freq */
-       if (abs((int)freq - clk0) <= abs((int)freq - clk1)) {
-               info->dsrc = src0;
-               if (div0) {
-                       info->ddiv |= 0x80000000;
-                       info->ddiv |= div0;
-               }
-               if (div1D) {
-                       info->mdiv |= 0x80000000;
-                       info->mdiv |= div1D;
-               }
-               info->ssel = 0;
-               info->freq = clk0;
-       } else {
-               if (div1P) {
-                       info->mdiv |= 0x80000000;
-                       info->mdiv |= div1P << 8;
-               }
-               info->ssel = (1 << clk);
-               info->dsrc = 0x40000100;
-               info->freq = clk1;
-       }
-
-       return 0;
-}
-
-static int
-nve0_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
-{
-       struct nve0_clock_priv *priv = (void *)clk;
-       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, 0x0c, nv_clk_src_daemon)) ||
-           (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec)))
-               return ret;
-
-       return 0;
-}
-
-static void
-nve0_clock_prog_0(struct nve0_clock_priv *priv, int clk)
-{
-       struct nve0_clock_info *info = &priv->eng[clk];
-       if (!info->ssel) {
-               nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x8000003f, info->ddiv);
-               nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc);
-       }
-}
-
-static void
-nve0_clock_prog_1_0(struct nve0_clock_priv *priv, int clk)
-{
-       nv_mask(priv, 0x137100, (1 << clk), 0x00000000);
-       nv_wait(priv, 0x137100, (1 << clk), 0x00000000);
-}
-
-static void
-nve0_clock_prog_1_1(struct nve0_clock_priv *priv, int clk)
-{
-       nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000000);
-}
-
-static void
-nve0_clock_prog_2(struct nve0_clock_priv *priv, int clk)
-{
-       struct nve0_clock_info *info = &priv->eng[clk];
-       const u32 addr = 0x137000 + (clk * 0x20);
-       nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000);
-       nv_mask(priv, 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);
-       }
-}
-
-static void
-nve0_clock_prog_3(struct nve0_clock_priv *priv, int clk)
-{
-       struct nve0_clock_info *info = &priv->eng[clk];
-       if (info->ssel)
-               nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f00, info->mdiv);
-       else
-               nv_mask(priv, 0x137250 + (clk * 0x04), 0x0000003f, info->mdiv);
-}
-
-static void
-nve0_clock_prog_4_0(struct nve0_clock_priv *priv, int clk)
-{
-       struct nve0_clock_info *info = &priv->eng[clk];
-       if (info->ssel) {
-               nv_mask(priv, 0x137100, (1 << clk), info->ssel);
-               nv_wait(priv, 0x137100, (1 << clk), info->ssel);
-       }
-}
-
-static void
-nve0_clock_prog_4_1(struct nve0_clock_priv *priv, int clk)
-{
-       struct nve0_clock_info *info = &priv->eng[clk];
-       if (info->ssel) {
-               nv_mask(priv, 0x137160 + (clk * 0x04), 0x40000000, 0x40000000);
-               nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000100);
-       }
-}
-
-static int
-nve0_clock_prog(struct nouveau_clock *clk)
-{
-       struct nve0_clock_priv *priv = (void *)clk;
-       struct {
-               u32 mask;
-               void (*exec)(struct nve0_clock_priv *, int);
-       } stage[] = {
-               { 0x007f, nve0_clock_prog_0   }, /* div programming */
-               { 0x007f, nve0_clock_prog_1_0 }, /* select div mode */
-               { 0xff80, nve0_clock_prog_1_1 },
-               { 0x00ff, nve0_clock_prog_2   }, /* (maybe) program pll */
-               { 0xff80, nve0_clock_prog_3   }, /* final divider */
-               { 0x007f, nve0_clock_prog_4_0 }, /* (maybe) select pll mode */
-               { 0xff80, nve0_clock_prog_4_1 },
-       };
-       int i, j;
-
-       for (i = 0; i < ARRAY_SIZE(stage); i++) {
-               for (j = 0; j < ARRAY_SIZE(priv->eng); j++) {
-                       if (!(stage[i].mask & (1 << j)))
-                               continue;
-                       if (!priv->eng[j].freq)
-                               continue;
-                       stage[i].exec(priv, j);
-               }
-       }
-
-       return 0;
-}
-
-static void
-nve0_clock_tidy(struct nouveau_clock *clk)
-{
-       struct nve0_clock_priv *priv = (void *)clk;
-       memset(priv->eng, 0x00, sizeof(priv->eng));
-}
-
-static struct nouveau_clocks
-nve0_domain[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_href   , 0xff },
-       { nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
-       { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
-       { nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
-       { nv_clk_src_mem    , 0x03, 0, "memory", 500 },
-       { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE },
-       { nv_clk_src_hubk01 , 0x05 },
-       { nv_clk_src_vdec   , 0x06 },
-       { nv_clk_src_daemon , 0x07 },
-       { nv_clk_src_max }
-};
-
-static int
-nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-               struct nouveau_oclass *oclass, void *data, u32 size,
-               struct nouveau_object **pobject)
-{
-       struct nve0_clock_priv *priv;
-       int ret;
-
-       ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, NULL, 0,
-                                  true, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.read = nve0_clock_read;
-       priv->base.calc = nve0_clock_calc;
-       priv->base.prog = nve0_clock_prog;
-       priv->base.tidy = nve0_clock_tidy;
-       return 0;
-}
-
-struct nouveau_oclass
-nve0_clock_oclass = {
-       .handle = NV_SUBDEV(CLOCK, 0xe0),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nve0_clock_ctor,
-               .dtor = _nouveau_clock_dtor,
-               .init = _nouveau_clock_init,
-               .fini = _nouveau_clock_fini,
-       },
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/pll.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/pll.h
deleted file mode 100644 (file)
index 445b14c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __NOUVEAU_PLL_H__
-#define __NOUVEAU_PLL_H__
-
-int nv04_pll_calc(struct nouveau_subdev *, struct nvbios_pll *, u32 freq,
-                 int *N1, int *M1, int *N2, int *M2, int *P);
-int nva3_pll_calc(struct nouveau_subdev *, struct nvbios_pll *, u32 freq,
-                 int *N, int *fN, int *M, int *P);
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/pllnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/pllnv04.c
deleted file mode 100644 (file)
index b47d543..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 1993-2003 NVIDIA, Corporation
- * Copyright 2007-2009 Stuart Bennett
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-
-#include "pll.h"
-
-static int
-getMNP_single(struct nouveau_subdev *subdev, struct nvbios_pll *info, int clk,
-             int *pN, int *pM, int *pP)
-{
-       /* Find M, N and P for a single stage PLL
-        *
-        * Note that some bioses (NV3x) have lookup tables of precomputed MNP
-        * values, but we're too lazy to use those atm
-        *
-        * "clk" parameter in kHz
-        * returns calculated clock
-        */
-       struct nouveau_bios *bios = nouveau_bios(subdev);
-       int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq;
-       int minM = info->vco1.min_m, maxM = info->vco1.max_m;
-       int minN = info->vco1.min_n, maxN = info->vco1.max_n;
-       int minU = info->vco1.min_inputfreq;
-       int maxU = info->vco1.max_inputfreq;
-       int minP = info->min_p;
-       int maxP = info->max_p_usable;
-       int crystal = info->refclk;
-       int M, N, thisP, P;
-       int clkP, calcclk;
-       int delta, bestdelta = INT_MAX;
-       int bestclk = 0;
-
-       /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */
-       /* possibly correlated with introduction of 27MHz crystal */
-       if (bios->version.major < 0x60) {
-               int cv = bios->version.chip;
-               if (cv < 0x17 || cv == 0x1a || cv == 0x20) {
-                       if (clk > 250000)
-                               maxM = 6;
-                       if (clk > 340000)
-                               maxM = 2;
-               } else if (cv < 0x40) {
-                       if (clk > 150000)
-                               maxM = 6;
-                       if (clk > 200000)
-                               maxM = 4;
-                       if (clk > 340000)
-                               maxM = 2;
-               }
-       }
-
-       P = 1 << maxP;
-       if ((clk * P) < minvco) {
-               minvco = clk * maxP;
-               maxvco = minvco * 2;
-       }
-
-       if (clk + clk/200 > maxvco)     /* +0.5% */
-               maxvco = clk + clk/200;
-
-       /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
-       for (thisP = minP; thisP <= maxP; thisP++) {
-               P = 1 << thisP;
-               clkP = clk * P;
-
-               if (clkP < minvco)
-                       continue;
-               if (clkP > maxvco)
-                       return bestclk;
-
-               for (M = minM; M <= maxM; M++) {
-                       if (crystal/M < minU)
-                               return bestclk;
-                       if (crystal/M > maxU)
-                               continue;
-
-                       /* add crystal/2 to round better */
-                       N = (clkP * M + crystal/2) / crystal;
-
-                       if (N < minN)
-                               continue;
-                       if (N > maxN)
-                               break;
-
-                       /* more rounding additions */
-                       calcclk = ((N * crystal + P/2) / P + M/2) / M;
-                       delta = abs(calcclk - clk);
-                       /* we do an exhaustive search rather than terminating
-                        * on an optimality condition...
-                        */
-                       if (delta < bestdelta) {
-                               bestdelta = delta;
-                               bestclk = calcclk;
-                               *pN = N;
-                               *pM = M;
-                               *pP = thisP;
-                               if (delta == 0) /* except this one */
-                                       return bestclk;
-                       }
-               }
-       }
-
-       return bestclk;
-}
-
-static int
-getMNP_double(struct nouveau_subdev *subdev, struct nvbios_pll *info, int clk,
-             int *pN1, int *pM1, int *pN2, int *pM2, int *pP)
-{
-       /* Find M, N and P for a two stage PLL
-        *
-        * Note that some bioses (NV30+) have lookup tables of precomputed MNP
-        * values, but we're too lazy to use those atm
-        *
-        * "clk" parameter in kHz
-        * returns calculated clock
-        */
-       int chip_version = nouveau_bios(subdev)->version.chip;
-       int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq;
-       int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq;
-       int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq;
-       int maxU1 = info->vco1.max_inputfreq, maxU2 = info->vco2.max_inputfreq;
-       int minM1 = info->vco1.min_m, maxM1 = info->vco1.max_m;
-       int minN1 = info->vco1.min_n, maxN1 = info->vco1.max_n;
-       int minM2 = info->vco2.min_m, maxM2 = info->vco2.max_m;
-       int minN2 = info->vco2.min_n, maxN2 = info->vco2.max_n;
-       int maxlog2P = info->max_p_usable;
-       int crystal = info->refclk;
-       bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2);
-       int M1, N1, M2, N2, log2P;
-       int clkP, calcclk1, calcclk2, calcclkout;
-       int delta, bestdelta = INT_MAX;
-       int bestclk = 0;
-
-       int vco2 = (maxvco2 - maxvco2/200) / 2;
-       for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++)
-               ;
-       clkP = clk << log2P;
-
-       if (maxvco2 < clk + clk/200)    /* +0.5% */
-               maxvco2 = clk + clk/200;
-
-       for (M1 = minM1; M1 <= maxM1; M1++) {
-               if (crystal/M1 < minU1)
-                       return bestclk;
-               if (crystal/M1 > maxU1)
-                       continue;
-
-               for (N1 = minN1; N1 <= maxN1; N1++) {
-                       calcclk1 = crystal * N1 / M1;
-                       if (calcclk1 < minvco1)
-                               continue;
-                       if (calcclk1 > maxvco1)
-                               break;
-
-                       for (M2 = minM2; M2 <= maxM2; M2++) {
-                               if (calcclk1/M2 < minU2)
-                                       break;
-                               if (calcclk1/M2 > maxU2)
-                                       continue;
-
-                               /* add calcclk1/2 to round better */
-                               N2 = (clkP * M2 + calcclk1/2) / calcclk1;
-                               if (N2 < minN2)
-                                       continue;
-                               if (N2 > maxN2)
-                                       break;
-
-                               if (!fixedgain2) {
-                                       if (chip_version < 0x60)
-                                               if (N2/M2 < 4 || N2/M2 > 10)
-                                                       continue;
-
-                                       calcclk2 = calcclk1 * N2 / M2;
-                                       if (calcclk2 < minvco2)
-                                               break;
-                                       if (calcclk2 > maxvco2)
-                                               continue;
-                               } else
-                                       calcclk2 = calcclk1;
-
-                               calcclkout = calcclk2 >> log2P;
-                               delta = abs(calcclkout - clk);
-                               /* we do an exhaustive search rather than terminating
-                                * on an optimality condition...
-                                */
-                               if (delta < bestdelta) {
-                                       bestdelta = delta;
-                                       bestclk = calcclkout;
-                                       *pN1 = N1;
-                                       *pM1 = M1;
-                                       *pN2 = N2;
-                                       *pM2 = M2;
-                                       *pP = log2P;
-                                       if (delta == 0) /* except this one */
-                                               return bestclk;
-                               }
-                       }
-               }
-       }
-
-       return bestclk;
-}
-
-int
-nv04_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info, u32 freq,
-             int *N1, int *M1, int *N2, int *M2, int *P)
-{
-       int ret;
-
-       if (!info->vco2.max_freq || !N2) {
-               ret = getMNP_single(subdev, info, freq, N1, M1, P);
-               if (N2) {
-                       *N2 = 1;
-                       *M2 = 1;
-               }
-       } else {
-               ret = getMNP_double(subdev, info, freq, N1, M1, N2, M2, P);
-       }
-
-       if (!ret)
-               nv_error(subdev, "unable to compute acceptable pll values\n");
-       return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/pllnva3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/pllnva3.c
deleted file mode 100644 (file)
index 8eca457..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2010 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <subdev/clock.h>
-#include <subdev/bios.h>
-#include <subdev/bios/pll.h>
-
-#include "pll.h"
-
-int
-nva3_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info,
-             u32 freq, int *pN, int *pfN, int *pM, int *P)
-{
-       u32 best_err = ~0, err;
-       int M, lM, hM, N, fN;
-
-       *P = info->vco1.max_freq / freq;
-       if (*P > info->max_p)
-               *P = info->max_p;
-       if (*P < info->min_p)
-               *P = info->min_p;
-
-       lM = (info->refclk + info->vco1.max_inputfreq) / info->vco1.max_inputfreq;
-       lM = max(lM, (int)info->vco1.min_m);
-       hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq;
-       hM = min(hM, (int)info->vco1.max_m);
-       lM = min(lM, hM);
-
-       for (M = lM; M <= hM; M++) {
-               u32 tmp = freq * *P * M;
-               N  = tmp / info->refclk;
-               fN = tmp % info->refclk;
-
-               if (!pfN) {
-                       if (fN >= info->refclk / 2)
-                               N++;
-               } else {
-                       if (fN <  info->refclk / 2)
-                               N--;
-                       fN = tmp - (N * info->refclk);
-               }
-
-               if (N < info->vco1.min_n)
-                       continue;
-               if (N > info->vco1.max_n)
-                       break;
-
-               err = abs(freq - (info->refclk * N / M / *P));
-               if (err < best_err) {
-                       best_err = err;
-                       *pN = N;
-                       *pM = M;
-               }
-
-               if (pfN) {
-                       *pfN = ((fN << 13) + info->refclk / 2) / info->refclk;
-                       *pfN = (*pfN - 4096) & 0xffff;
-                       return freq;
-               }
-       }
-
-       if (unlikely(best_err == ~0)) {
-               nv_error(subdev, "unable to find matching pll values\n");
-               return -EINVAL;
-       }
-
-       return info->refclk * *pN / *pM / *P;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clock/seq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/clock/seq.h
deleted file mode 100644 (file)
index fb33f06..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __NVKM_CLK_SEQ_H__
-#define __NVKM_CLK_SEQ_H__
-
-#include <subdev/bus.h>
-#include <subdev/bus/hwsq.h>
-
-#define clk_init(s,p)       hwsq_init(&(s)->base, (p))
-#define clk_exec(s,e)       hwsq_exec(&(s)->base, (e))
-#define clk_have(s,r)       ((s)->r_##r.addr != 0x000000)
-#define clk_rd32(s,r)       hwsq_rd32(&(s)->base, &(s)->r_##r)
-#define clk_wr32(s,r,d)     hwsq_wr32(&(s)->base, &(s)->r_##r, (d))
-#define clk_mask(s,r,m,d)   hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d))
-#define clk_setf(s,f,d)     hwsq_setf(&(s)->base, (f), (d))
-#define clk_wait(s,f,d)     hwsq_wait(&(s)->base, (f), (d))
-#define clk_nsec(s,n)       hwsq_nsec(&(s)->base, (n))
-
-#endif
index cbcd51852472aa54ab0667bb0b9f3bac03cd2cac..7a768afba813d0d6c029343c0aef1cfb9b835bd4 100644 (file)
@@ -4,7 +4,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/init.h>
-#include <subdev/clock/pll.h>
+#include <subdev/clk/pll.h>
 #include <subdev/devinit.h>
 
 struct nouveau_devinit_impl {
index 7648beb1119900eb162fe591f4990be8bba21410..50cbc3804eafa56b0b277d6493bc421b3f34f8b0 100644 (file)
@@ -26,8 +26,8 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/init.h>
-#include <subdev/clock.h>
-#include <subdev/clock/pll.h>
+#include <subdev/clk.h>
+#include <subdev/clk/pll.h>
 #include <subdev/timer.h>
 
 #include <engine/fifo.h>
index 64a983c9662576bad70207aad209564b32cd6b4f..8d2970c2771505f4b3d6810c7f9bb128758d8c5e 100644 (file)
@@ -27,7 +27,7 @@
 #include <subdev/bios/pll.h>
 #include <subdev/bios/perf.h>
 #include <subdev/bios/timing.h>
-#include <subdev/clock/pll.h>
+#include <subdev/clk/pll.h>
 #include <subdev/fb.h>
 
 #include <core/option.h>
index 3b38a538845d70fc9b714c6cda72740942b4dec6..50e8dee513cc75692ef9ea9e79932ba675f5a1c8 100644 (file)
@@ -30,8 +30,8 @@
 #include <subdev/bios/M0205.h>
 #include <subdev/bios/timing.h>
 
-#include <subdev/clock/nva3.h>
-#include <subdev/clock/pll.h>
+#include <subdev/clk/nva3.h>
+#include <subdev/clk/pll.h>
 
 #include <subdev/gpio.h>
 
@@ -168,7 +168,7 @@ nva3_link_train(struct nouveau_fb *pfb)
 {
        struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nva3_ram *ram = (void *)pfb->ram;
-       struct nouveau_clock *clk = nouveau_clock(pfb);
+       struct nouveau_clk *clk = nouveau_clk(pfb);
        struct nva3_ltrain *train = &ram->ltrain;
        struct nouveau_device *device = nv_device(pfb);
        struct nva3_ramfuc *fuc = &ram->fuc;
@@ -197,7 +197,7 @@ nva3_link_train(struct nouveau_fb *pfb)
 
        clk_current = clk->read(clk, nv_clk_src_mem);
 
-       ret = nva3_clock_pre(clk, f);
+       ret = nva3_clk_pre(clk, f);
        if (ret)
                goto out;
 
@@ -252,7 +252,7 @@ nva3_link_train(struct nouveau_fb *pfb)
        nv_mask(pfb, 0x616308, 0x10, 0x10);
        nv_mask(pfb, 0x616b08, 0x10, 0x10);
 
-       nva3_clock_post(clk, f);
+       nva3_clk_post(clk, f);
 
        ram_train_result(pfb, result, 64);
        for (i = 0; i < 64; i++)
@@ -274,7 +274,7 @@ out:
 
        train->state = NVA3_TRAIN_UNSUPPORTED;
 
-       nva3_clock_post(clk, f);
+       nva3_clk_post(clk, f);
        return ret;
 }
 
@@ -465,7 +465,7 @@ nouveau_gddr3_dll_disable(struct nva3_ramfuc *fuc, u32 *mr)
 }
 
 static void
-nva3_ram_lock_pll(struct nva3_ramfuc *fuc, struct nva3_clock_info *mclk)
+nva3_ram_lock_pll(struct nva3_ramfuc *fuc, struct nva3_clk_info *mclk)
 {
        ram_wr32(fuc, 0x004004, mclk->pll);
        ram_mask(fuc, 0x004000, 0x00000001, 0x00000001);
@@ -504,7 +504,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nva3_ram *ram = (void *)pfb->ram;
        struct nva3_ramfuc *fuc = &ram->fuc;
        struct nva3_ltrain *train = &ram->ltrain;
-       struct nva3_clock_info mclk;
+       struct nva3_clk_info mclk;
        struct nouveau_ram_data *next;
        u8  ver, hdr, cnt, len, strap;
        u32 data;
@@ -555,7 +555,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
                }
        }
 
-       ret = nva3_pll_info(nouveau_clock(pfb), 0x12, 0x4000, freq, &mclk);
+       ret = nva3_pll_info(nouveau_clk(pfb), 0x12, 0x4000, freq, &mclk);
        if (ret < 0) {
                nv_error(pfb, "failed mclk calculation\n");
                return ret;
index 735cb9580abe88330efe78b8718378b619d4d66d..d08eacd580d4160437e9ac5a7867edcaef25ca14 100644 (file)
@@ -28,8 +28,8 @@
 #include <subdev/bios/timing.h>
 #include <subdev/ltc.h>
 
-#include <subdev/clock.h>
-#include <subdev/clock/pll.h>
+#include <subdev/clk.h>
+#include <subdev/clk/pll.h>
 
 #include <core/option.h>
 
@@ -129,7 +129,7 @@ nvc0_ram_train(struct nvc0_ramfuc *fuc, u32 magic)
 static int
 nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 {
-       struct nouveau_clock *clk = nouveau_clock(pfb);
+       struct nouveau_clk *clk = nouveau_clk(pfb);
        struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nvc0_ram *ram = (void *)pfb->ram;
        struct nvc0_ramfuc *fuc = &ram->fuc;
index 6bae474abb4476ed46510b74000c68b457e817f4..60050aab84b8c52f722adebed0833acdb405566e 100644 (file)
@@ -32,8 +32,8 @@
 #include <subdev/bios/M0205.h>
 #include <subdev/bios/M0209.h>
 
-#include <subdev/clock.h>
-#include <subdev/clock/pll.h>
+#include <subdev/clk.h>
+#include <subdev/clk/pll.h>
 
 #include <subdev/timer.h>
 
@@ -1033,7 +1033,7 @@ nve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next)
 static int
 nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 {
-       struct nouveau_clock *clk = nouveau_clock(pfb);
+       struct nouveau_clk *clk = nouveau_clk(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nouveau_ram_data *xits = &ram->base.xition;
        struct nouveau_ram_data *copy;
index f6b7df1b1686f598e1fd1752506db2a65b200d7a..a4e3a9b57306f22a3afd34008c5281d67e8c5d1f 100644 (file)
@@ -21,7 +21,7 @@
  */
 #include "priv.h"
 
-#include <subdev/clock.h>
+#include <subdev/clk.h>
 #include <subdev/timer.h>
 #include <subdev/volt.h>
 
@@ -50,15 +50,15 @@ struct gk20a_pwr_dvfs_dev_status {
 static int
 gk20a_pwr_dvfs_target(struct gk20a_pwr_priv *priv, int *state)
 {
-       struct nouveau_clock *clk = nouveau_clock(priv);
+       struct nouveau_clk *clk = nouveau_clk(priv);
 
-       return nouveau_clock_astate(clk, *state, 0, false);
+       return nouveau_clk_astate(clk, *state, 0, false);
 }
 
 static int
 gk20a_pwr_dvfs_get_cur_state(struct gk20a_pwr_priv *priv, int *state)
 {
-       struct nouveau_clock *clk = nouveau_clock(priv);
+       struct nouveau_clk *clk = nouveau_clk(priv);
 
        *state = clk->pstate;
        return 0;
@@ -69,7 +69,7 @@ gk20a_pwr_dvfs_get_target_state(struct gk20a_pwr_priv *priv,
                int *state, int load)
 {
        struct gk20a_pwr_dvfs_data *data = priv->data;
-       struct nouveau_clock *clk = nouveau_clock(priv);
+       struct nouveau_clk *clk = nouveau_clk(priv);
        int cur_level, level;
 
        /* For GK20A, the performance level is directly mapped to pstate */
@@ -117,7 +117,7 @@ gk20a_pwr_dvfs_work(struct nouveau_alarm *alarm)
                                        struct gk20a_pwr_priv, alarm);
        struct gk20a_pwr_dvfs_data *data = priv->data;
        struct gk20a_pwr_dvfs_dev_status status;
-       struct nouveau_clock *clk = nouveau_clock(priv);
+       struct nouveau_clk *clk = nouveau_clk(priv);
        struct nouveau_volt *volt = nouveau_volt(priv);
        u32 utilization = 0;
        int state, ret;