summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c72
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 fb04d5cd34bf..cc6d0796c265 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 4105175dfccd..ec3eedfa541a 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 3aa042eec104..62e81d551f44 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 626b64230fe5..fd5c6931322d 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 <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 } },
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h
index e6f436532392..96d53c02041b 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 <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
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c
index 9e1745d31fbb..3d063fb5e136 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 <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 } },
};