From e650738055cebe1dec82765232697052bf6c22d5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Jun 2022 20:46:54 +1000 Subject: [PATCH] drm/nouveau/vfn/tu102-: support new-style interrupt tree - switches ampere over now, and removes its hack mc implementation Signed-off-by: Ben Skeggs Reviewed-by: Lyude Paul --- drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h | 2 + drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c | 16 +---- drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c | 8 +++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c | 11 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h | 5 ++ drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c | 72 +++++++++++++++++++++++ 6 files changed, 99 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h index fb04d5c..cc6d079 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h @@ -12,6 +12,8 @@ struct nvkm_vfn { u32 user; } addr; + struct nvkm_intr intr; + struct nvkm_device_oclass user; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c index 4105175..ec3eedf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c @@ -24,36 +24,23 @@ 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, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c index 3aa042e..62e81d5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c index 626b642..fd5c693 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c @@ -23,8 +23,19 @@ #include +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 } }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h index e6f4365..96d53c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h @@ -5,6 +5,9 @@ #include 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 diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c index 9e1745d..3d063fb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c @@ -23,8 +23,80 @@ #include +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 } }, }; -- 2.7.4