[v5,17/18] falcon: add clear_interrupt function

Submitted by Alexandre Courbot on Dec. 14, 2016, 8:02 a.m.

Details

Message ID e980b8e6d2def001877c74614cb78da17e4dbe5c.1481702469.git-series.acourbot@nvidia.com
State New
Headers show
Series "Secure Boot refactoring" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Alexandre Courbot Dec. 14, 2016, 8:02 a.m.
Allow users to clear interrupt flags.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
 drm/nouveau/include/nvkm/engine/falcon.h |  2 ++
 drm/nouveau/nvkm/falcon/base.c           |  6 ++++++
 drm/nouveau/nvkm/falcon/v1.c             | 17 +++++++++++++++++
 3 files changed, 25 insertions(+), 0 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/include/nvkm/engine/falcon.h b/drm/nouveau/include/nvkm/engine/falcon.h
index 4fc19f46e643..7e498e65b1e8 100644
--- a/drm/nouveau/include/nvkm/engine/falcon.h
+++ b/drm/nouveau/include/nvkm/engine/falcon.h
@@ -70,6 +70,7 @@  struct nvkm_falcon_func {
 	void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *);
 	void (*bind_context)(struct nvkm_falcon *, struct nvkm_gpuobj *);
 	int (*wait_for_halt)(struct nvkm_falcon *, u32);
+	int (*clear_interrupt)(struct nvkm_falcon *, u32);
 	void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr);
 	void (*start)(struct nvkm_falcon *);
 	int (*enable)(struct nvkm_falcon *falcon);
@@ -106,6 +107,7 @@  void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_gpuobj *);
 void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32);
 void nvkm_falcon_start(struct nvkm_falcon *);
 int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32);
+int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32);
 int nvkm_falcon_enable(struct nvkm_falcon *);
 void nvkm_falcon_disable(struct nvkm_falcon *);
 int nvkm_falcon_reset(struct nvkm_falcon *);
diff --git a/drm/nouveau/nvkm/falcon/base.c b/drm/nouveau/nvkm/falcon/base.c
index a3935ae7f91b..31f83c7986d6 100644
--- a/drm/nouveau/nvkm/falcon/base.c
+++ b/drm/nouveau/nvkm/falcon/base.c
@@ -120,6 +120,12 @@  nvkm_falcon_wait_for_halt(struct nvkm_falcon *falcon, u32 ms)
 	return falcon->func->wait_for_halt(falcon, ms);
 }
 
+int
+nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
+{
+	return falcon->func->clear_interrupt(falcon, mask);
+}
+
 void
 nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
 {
diff --git a/drm/nouveau/nvkm/falcon/v1.c b/drm/nouveau/nvkm/falcon/v1.c
index e30d9580e455..24a295858287 100644
--- a/drm/nouveau/nvkm/falcon/v1.c
+++ b/drm/nouveau/nvkm/falcon/v1.c
@@ -179,6 +179,22 @@  nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms)
 }
 
 static int
+nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
+{
+	struct nvkm_device *device = falcon->owner->device;
+	int ret;
+
+	/* clear interrupt(s) */
+	nvkm_falcon_mask(falcon, 0x004, mask, mask);
+	/* wait until interrupts are cleared */
+	ret = nvkm_wait_msec(device, 10, falcon->addr + 0x008, mask, 0x0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int
 falcon_v1_wait_idle(struct nvkm_falcon *falcon)
 {
 	struct nvkm_device *device = falcon->owner->device;
@@ -229,6 +245,7 @@  nvkm_falcon_v1 = {
 	.bind_context = nvkm_falcon_v1_bind_context,
 	.start = nvkm_falcon_v1_start,
 	.wait_for_halt = nvkm_falcon_v1_wait_for_halt,
+	.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
 	.enable = nvkm_falcon_v1_enable,
 	.disable = nvkm_falcon_v1_disable,
 	.set_start_addr = nvkm_falcon_v1_set_start_addr,