From 57f7422016c5289baf906cdad55b326d05c26519 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 24 Feb 2014 12:41:57 +1000 Subject: [PATCH] drm/gk20a/timer: initial implementation A bit different from NVIDIA's RFC patch, but I want this now for GM107. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 1 + .../drm/nouveau/core/include/subdev/timer.h | 1 + .../gpu/drm/nouveau/core/subdev/timer/gk20a.c | 57 +++++++++++++ .../gpu/drm/nouveau/core/subdev/timer/nv04.c | 83 ++++++++----------- .../gpu/drm/nouveau/core/subdev/timer/nv04.h | 27 ++++++ .../gpu/drm/nouveau/core/subdev/timer/priv.h | 6 ++ 6 files changed, 126 insertions(+), 49 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/timer/priv.h diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index d82b7d26d09b..d2810522a2b5 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -171,6 +171,7 @@ nouveau-y += core/subdev/therm/nva3.o nouveau-y += core/subdev/therm/nvd0.o nouveau-y += core/subdev/timer/base.o nouveau-y += core/subdev/timer/nv04.o +nouveau-y += core/subdev/timer/gk20a.o nouveau-y += core/subdev/vm/base.o nouveau-y += core/subdev/vm/nv04.o nouveau-y += core/subdev/vm/nv41.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index 9ab70dfe5b02..db9be803a874 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h @@ -59,5 +59,6 @@ int nouveau_timer_create_(struct nouveau_object *, struct nouveau_engine *, struct nouveau_oclass *, int size, void **); extern struct nouveau_oclass nv04_timer_oclass; +extern struct nouveau_oclass gk20a_timer_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c new file mode 100644 index 000000000000..37484db1f7fc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c @@ -0,0 +1,57 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv04.h" + +static int +gk20a_timer_init(struct nouveau_object *object) +{ + struct nv04_timer_priv *priv = (void *)object; + u32 hi = upper_32_bits(priv->suspend_time); + u32 lo = lower_32_bits(priv->suspend_time); + int ret; + + ret = nouveau_timer_init(&priv->base); + if (ret) + return ret; + + nv_debug(priv, "time low : 0x%08x\n", lo); + nv_debug(priv, "time high : 0x%08x\n", hi); + + /* restore the time before suspend */ + nv_wr32(priv, NV04_PTIMER_TIME_1, hi); + nv_wr32(priv, NV04_PTIMER_TIME_0, lo); + return 0; +} + +struct nouveau_oclass +gk20a_timer_oclass = { + .handle = NV_SUBDEV(TIMER, 0xff), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nv04_timer_ctor, + .dtor = nv04_timer_dtor, + .init = gk20a_timer_init, + .fini = nv04_timer_fini, + } +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index c0bdd10358d7..240ed0b983a9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -22,22 +22,7 @@ * Authors: Ben Skeggs */ -#include - -#define NV04_PTIMER_INTR_0 0x009100 -#define NV04_PTIMER_INTR_EN_0 0x009140 -#define NV04_PTIMER_NUMERATOR 0x009200 -#define NV04_PTIMER_DENOMINATOR 0x009210 -#define NV04_PTIMER_TIME_0 0x009400 -#define NV04_PTIMER_TIME_1 0x009410 -#define NV04_PTIMER_ALARM_0 0x009420 - -struct nv04_timer_priv { - struct nouveau_timer base; - struct list_head alarms; - spinlock_t lock; - u64 suspend_time; -}; +#include "nv04.h" static u64 nv04_timer_read(struct nouveau_timer *ptimer) @@ -142,35 +127,14 @@ nv04_timer_intr(struct nouveau_subdev *subdev) } } -static int -nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv04_timer_priv *priv; - int ret; - - ret = nouveau_timer_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.intr = nv04_timer_intr; - priv->base.read = nv04_timer_read; - priv->base.alarm = nv04_timer_alarm; - priv->base.alarm_cancel = nv04_timer_alarm_cancel; - priv->suspend_time = 0; - - INIT_LIST_HEAD(&priv->alarms); - spin_lock_init(&priv->lock); - return 0; -} - -static void -nv04_timer_dtor(struct nouveau_object *object) +int +nv04_timer_fini(struct nouveau_object *object, bool suspend) { struct nv04_timer_priv *priv = (void *)object; - return nouveau_timer_destroy(&priv->base); + if (suspend) + priv->suspend_time = nv04_timer_read(&priv->base); + nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); + return nouveau_timer_fini(&priv->base, suspend); } static int @@ -257,14 +221,35 @@ nv04_timer_init(struct nouveau_object *object) return 0; } -static int -nv04_timer_fini(struct nouveau_object *object, bool suspend) +void +nv04_timer_dtor(struct nouveau_object *object) { struct nv04_timer_priv *priv = (void *)object; - if (suspend) - priv->suspend_time = nv04_timer_read(&priv->base); - nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); - return nouveau_timer_fini(&priv->base, suspend); + return nouveau_timer_destroy(&priv->base); +} + +int +nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nv04_timer_priv *priv; + int ret; + + ret = nouveau_timer_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + priv->base.base.intr = nv04_timer_intr; + priv->base.read = nv04_timer_read; + priv->base.alarm = nv04_timer_alarm; + priv->base.alarm_cancel = nv04_timer_alarm_cancel; + priv->suspend_time = 0; + + INIT_LIST_HEAD(&priv->alarms); + spin_lock_init(&priv->lock); + return 0; } struct nouveau_oclass diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h new file mode 100644 index 000000000000..4bc152697c37 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h @@ -0,0 +1,27 @@ +#ifndef __NVKM_TIMER_NV04_H__ +#define __NVKM_TIMER_NV04_H__ + +#include "priv.h" + +#define NV04_PTIMER_INTR_0 0x009100 +#define NV04_PTIMER_INTR_EN_0 0x009140 +#define NV04_PTIMER_NUMERATOR 0x009200 +#define NV04_PTIMER_DENOMINATOR 0x009210 +#define NV04_PTIMER_TIME_0 0x009400 +#define NV04_PTIMER_TIME_1 0x009410 +#define NV04_PTIMER_ALARM_0 0x009420 + +struct nv04_timer_priv { + struct nouveau_timer base; + struct list_head alarms; + spinlock_t lock; + u64 suspend_time; +}; + +int nv04_timer_ctor(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, void *, u32, + struct nouveau_object **); +void nv04_timer_dtor(struct nouveau_object *); +int nv04_timer_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h new file mode 100644 index 000000000000..799dae3f2300 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h @@ -0,0 +1,6 @@ +#ifndef __NVKM_TIMER_PRIV_H__ +#define __NVKM_TIMER_PRIV_H__ + +#include + +#endif