Commit e6507380 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/vfn/tu102-: support new-style interrupt tree

- switches ampere over now, and removes its hack mc implementation
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 58c3d3c8
......@@ -12,6 +12,8 @@ struct nvkm_vfn {
u32 user;
} addr;
struct nvkm_intr intr;
struct nvkm_device_oclass user;
};
......
......@@ -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,
};
......
......@@ -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;
......
......@@ -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 } },
};
......
......@@ -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
......@@ -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 } },
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment