drm/nouveau/mc: expose device enable/disable separately, as well as reset
authorBen Skeggs <bskeggs@redhat.com>
Sun, 29 May 2016 22:23:41 +0000 (08:23 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 14 Jul 2016 01:53:25 +0000 (11:53 +1000)
There are cases where subdevs need to perform additonal actions around
the master reset, so we want to expost the operations separately.

This commit also adds a flag to the NV_PMC_ENABLE bitfield definitions
which allow skipping the automatic reset() called from core/subdev.c.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h

index 45e6953..c5f1235 100644 (file)
@@ -7,10 +7,12 @@ struct nvkm_mc {
        struct nvkm_subdev subdev;
 };
 
+void nvkm_mc_enable(struct nvkm_device *, enum nvkm_devidx);
+void nvkm_mc_disable(struct nvkm_device *, enum nvkm_devidx);
+void nvkm_mc_reset(struct nvkm_device *, enum nvkm_devidx);
 void nvkm_mc_intr(struct nvkm_device *, bool *handled);
 void nvkm_mc_intr_unarm(struct nvkm_device *);
 void nvkm_mc_intr_rearm(struct nvkm_device *);
-void nvkm_mc_reset(struct nvkm_device *, enum nvkm_devidx);
 void nvkm_mc_unk260(struct nvkm_device *, u32 data);
 
 int nv04_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
index 563a528..e887df0 100644 (file)
@@ -95,22 +95,32 @@ nvkm_mc_intr(struct nvkm_device *device, bool *handled)
        *handled = intr != 0;
 }
 
-static void
-nvkm_mc_reset_(struct nvkm_mc *mc, enum nvkm_devidx devidx)
+static u32
+nvkm_mc_reset_mask(struct nvkm_device *device, bool isauto,
+                  enum nvkm_devidx devidx)
 {
-       struct nvkm_device *device = mc->subdev.device;
+       struct nvkm_mc *mc = device->mc;
        const struct nvkm_mc_map *map;
-       u64 pmc_enable;
-
-       if (!(pmc_enable = nvkm_top_reset(device, devidx))) {
-               for (map = mc->func->reset; map && map->stat; map++) {
-                       if (map->unit == devidx) {
-                               pmc_enable = map->stat;
-                               break;
+       u64 pmc_enable = 0;
+       if (likely(mc)) {
+               if (!(pmc_enable = nvkm_top_reset(device, devidx))) {
+                       for (map = mc->func->reset; map && map->stat; map++) {
+                               if (!isauto || !map->noauto) {
+                                       if (map->unit == devidx) {
+                                               pmc_enable = map->stat;
+                                               break;
+                                       }
+                               }
                        }
                }
        }
+       return pmc_enable;
+}
 
+void
+nvkm_mc_reset(struct nvkm_device *device, enum nvkm_devidx devidx)
+{
+       u64 pmc_enable = nvkm_mc_reset_mask(device, true, devidx);
        if (pmc_enable) {
                nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
                nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
@@ -119,11 +129,21 @@ nvkm_mc_reset_(struct nvkm_mc *mc, enum nvkm_devidx devidx)
 }
 
 void
-nvkm_mc_reset(struct nvkm_device *device, enum nvkm_devidx devidx)
+nvkm_mc_disable(struct nvkm_device *device, enum nvkm_devidx devidx)
 {
-       struct nvkm_mc *mc = device->mc;
-       if (likely(mc))
-               nvkm_mc_reset_(mc, devidx);
+       u64 pmc_enable = nvkm_mc_reset_mask(device, false, devidx);
+       if (pmc_enable)
+               nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
+}
+
+void
+nvkm_mc_enable(struct nvkm_device *device, enum nvkm_devidx devidx)
+{
+       u64 pmc_enable = nvkm_mc_reset_mask(device, false, devidx);
+       if (pmc_enable) {
+               nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
+               nvkm_rd32(device, 0x000200);
+       }
 }
 
 static int
index 536b8bd..bace7fc 100644 (file)
@@ -11,6 +11,7 @@ int nvkm_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *,
 struct nvkm_mc_map {
        u32 stat;
        u32 unit;
+       bool noauto;
 };
 
 struct nvkm_mc_func {