drm/nouveau/vfn/tu102-: support new-style interrupt tree
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:46:54 +0000 (20:46 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 9 Nov 2022 00:44:36 +0000 (10:44 +1000)
- switches ampere over now, and removes its hack mc implementation

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h
drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c
drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c
drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c

index fb04d5c..cc6d079 100644 (file)
@@ -12,6 +12,8 @@ struct nvkm_vfn {
                u32 user;
        } addr;
 
+       struct nvkm_intr intr;
+
        struct nvkm_device_oclass user;
 };
 
index 4105175..ec3eedf 100644 (file)
 static void
 ga100_mc_intr_unarm(struct nvkm_mc *mc)
 {
-       nvkm_wr32(mc->subdev.device, 0xb81610, 0x00000004);
 }
 
 static void
 ga100_mc_intr_rearm(struct nvkm_mc *mc)
 {
-       nvkm_wr32(mc->subdev.device, 0xb81608, 0x00000004);
-}
-
-static void
-ga100_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 intr)
-{
-       nvkm_wr32(mc->subdev.device, 0xb81210,          mask & intr );
-       nvkm_wr32(mc->subdev.device, 0xb81410, mask & ~(mask & intr));
 }
 
 static u32
 ga100_mc_intr_stat(struct nvkm_mc *mc)
 {
-       u32 intr_top = nvkm_rd32(mc->subdev.device, 0xb81600), intr = 0x00000000;
-       if (intr_top & 0x00000004)
-               intr = nvkm_mask(mc->subdev.device, 0xb81010, 0x00000000, 0x00000000);
-       return intr;
+       return 0;
 }
 
 static void
 ga100_mc_init(struct nvkm_mc *mc)
 {
        nv50_mc_init(mc);
-       nvkm_wr32(mc->subdev.device, 0xb81210, 0xffffffff);
 }
 
 static const struct nvkm_mc_func
@@ -62,7 +49,6 @@ ga100_mc = {
        .intr = gp100_mc_intr,
        .intr_unarm = ga100_mc_intr_unarm,
        .intr_rearm = ga100_mc_intr_rearm,
-       .intr_mask = ga100_mc_intr_mask,
        .intr_stat = ga100_mc_intr_stat,
        .reset = gk104_mc_reset,
 };
index 3aa042e..62e81d5 100644 (file)
@@ -37,6 +37,7 @@ nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device,
              enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_vfn **pvfn)
 {
        struct nvkm_vfn *vfn;
+       int ret;
 
        if (!(vfn = *pvfn = kzalloc(sizeof(*vfn), GFP_KERNEL)))
                return -ENOMEM;
@@ -46,6 +47,13 @@ nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device,
        vfn->addr.priv = addr;
        vfn->addr.user = vfn->addr.priv + func->user.addr;
 
+       if (vfn->func->intr) {
+               ret = nvkm_intr_add(vfn->func->intr, vfn->func->intrs,
+                                   &vfn->subdev, 8, &vfn->intr);
+               if (ret)
+                       return ret;
+       }
+
        vfn->user.ctor = nvkm_uvfn_new;
        vfn->user.base = func->user.base;
        return 0;
index 626b642..fd5c693 100644 (file)
 
 #include <nvif/class.h>
 
+static const struct nvkm_intr_data
+ga100_vfn_intrs[] = {
+       { NVKM_ENGINE_DISP    , 0, 4, 0x04000000, true },
+       { NVKM_SUBDEV_GPIO    , 0, 4, 0x00200000, true },
+       { NVKM_SUBDEV_I2C     , 0, 4, 0x00200000, true },
+       { NVKM_SUBDEV_PRIVRING, 0, 4, 0x40000000, true },
+       {}
+};
+
 static const struct nvkm_vfn_func
 ga100_vfn = {
+       .intr = &tu102_vfn_intr,
+       .intrs = ga100_vfn_intrs,
        .user = { 0x030000, 0x010000, { -1, -1, AMPERE_USERMODE_A } },
 };
 
index e6f4365..96d53c0 100644 (file)
@@ -5,6 +5,9 @@
 #include <subdev/vfn.h>
 
 struct nvkm_vfn_func {
+       const struct nvkm_intr_func *intr;
+       const struct nvkm_intr_data *intrs;
+
        struct {
                u32 addr;
                u32 size;
@@ -15,6 +18,8 @@ struct nvkm_vfn_func {
 int nvkm_vfn_new_(const struct nvkm_vfn_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
                  u32 addr, struct nvkm_vfn **);
 
+extern const struct nvkm_intr_func tu102_vfn_intr;
+
 int nvkm_uvfn_new(struct nvkm_device *, const struct nvkm_oclass *, void *, u32,
                  struct nvkm_object **);
 #endif
index 9e1745d..3d063fb 100644 (file)
 
 #include <nvif/class.h>
 
+static void
+tu102_vfn_intr_reset(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+       struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+       nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1000 + (leaf * 4), mask);
+}
+
+static void
+tu102_vfn_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+       struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+       nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1200 + (leaf * 4), mask);
+}
+
+static void
+tu102_vfn_intr_block(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+       struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+       nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1400 + (leaf * 4), mask);
+}
+
+static void
+tu102_vfn_intr_rearm(struct nvkm_intr *intr)
+{
+       struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+       nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1608, 0x0000000f);
+}
+
+static void
+tu102_vfn_intr_unarm(struct nvkm_intr *intr)
+{
+       struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+       nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1610, 0x0000000f);
+}
+
+static bool
+tu102_vfn_intr_pending(struct nvkm_intr *intr)
+{
+       struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+       struct nvkm_device *device = vfn->subdev.device;
+       u32 intr_top = nvkm_rd32(device, vfn->addr.priv + 0x1600);
+       int pending = 0, leaf;
+
+       for (leaf = 0; leaf < 8; leaf++) {
+               if (intr_top & BIT(leaf / 2)) {
+                       intr->stat[leaf] = nvkm_rd32(device, vfn->addr.priv + 0x1000 + (leaf * 4));
+                       if (intr->stat[leaf])
+                               pending++;
+               } else {
+                       intr->stat[leaf] = 0;
+               }
+       }
+
+       return pending != 0;
+}
+
+const struct nvkm_intr_func
+tu102_vfn_intr = {
+       .pending = tu102_vfn_intr_pending,
+       .unarm = tu102_vfn_intr_unarm,
+       .rearm = tu102_vfn_intr_rearm,
+       .block = tu102_vfn_intr_block,
+       .allow = tu102_vfn_intr_allow,
+       .reset = tu102_vfn_intr_reset,
+};
+
 static const struct nvkm_vfn_func
 tu102_vfn = {
+       .intr = &tu102_vfn_intr,
        .user = { 0x030000, 0x010000, { -1, -1, TURING_USERMODE_A } },
 };