Commit 5a5c7432 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/timer: port to subdev interfaces

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7d9115de
......@@ -75,6 +75,7 @@ nouveau-y += core/subdev/mc/nv44.o
nouveau-y += core/subdev/mc/nv50.o
nouveau-y += core/subdev/mc/nv98.o
nouveau-y += core/subdev/mc/nvc0.o
nouveau-y += core/subdev/timer/base.o
nouveau-y += core/subdev/timer/nv04.o
nouveau-y += core/subdev/vm/base.o
nouveau-y += core/subdev/vm/nv50.o
......
......@@ -224,7 +224,6 @@ static void
nv84_graph_tlb_flush(struct drm_device *dev, int engine)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
bool idle, timeout = false;
unsigned long flags;
u64 start;
......@@ -233,7 +232,7 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine)
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
nv_mask(dev, 0x400500, 0x00000001, 0x00000000);
start = ptimer->read(dev);
start = nv_timer_read(dev);
do {
idle = true;
......@@ -251,7 +250,7 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine)
if ((tmp & 7) == 1)
idle = false;
}
} while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000));
} while (!idle && !(timeout = nv_timer_read(dev) - start > 2000000000));
if (timeout) {
NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: "
......
#ifndef __NOUVEAU_TIMER_H__
#define __NOUVEAU_TIMER_H__
#include <core/subdev.h>
#include <core/device.h>
struct nouveau_alarm {
struct list_head head;
u64 timestamp;
void (*func)(struct nouveau_alarm *);
};
bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data);
bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data);
bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *);
#define NV_WAIT_DEFAULT 2000000000ULL
#define nv_wait(o,a,m,v) \
nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v))
#define nv_wait_ne(o,a,m,v) \
nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v))
#define nv_wait_cb(o,a,m,v) \
nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (a), (m), (v))
struct nouveau_timer {
struct nouveau_subdev base;
u64 (*read)(struct nouveau_timer *);
void (*alarm)(struct nouveau_timer *, u32 time, struct nouveau_alarm *);
};
static inline struct nouveau_timer *
nouveau_timer(void *obj)
{
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_TIMER];
}
#define nouveau_timer_create(p,e,o,d) \
nouveau_subdev_create_((p), (e), (o), 0, "PTIMER", "timer", \
sizeof(**d), (void **)d)
#define nouveau_timer_destroy(p) \
nouveau_subdev_destroy(&(p)->base)
#define nouveau_timer_init(p) \
nouveau_subdev_init(&(p)->base)
#define nouveau_timer_fini(p,s) \
nouveau_subdev_fini(&(p)->base, (s))
int nouveau_timer_create_(struct nouveau_object *, struct nouveau_engine *,
struct nouveau_oclass *, int size, void **);
extern struct nouveau_oclass nv04_timer_oclass;
#endif
......@@ -28,6 +28,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nv04_identify(struct nouveau_device *device)
......@@ -39,6 +40,7 @@ nv04_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x05:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -46,6 +48,7 @@ nv04_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown RIVA chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nv10_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x15:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x16:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -57,6 +60,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x1a:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -65,6 +69,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x11:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -73,6 +78,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x17:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -81,6 +87,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x1f:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -89,6 +96,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x18:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -97,6 +105,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Celsius chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nv20_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x25:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x28:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -57,6 +60,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x2a:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -65,6 +69,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Kelvin chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nv30_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x35:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x31:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -57,6 +60,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x36:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -65,6 +69,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x34:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -73,6 +78,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Rankine chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nv40_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x41:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x42:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -57,6 +60,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x43:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -65,6 +69,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x45:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -73,6 +78,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x47:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -81,6 +87,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x49:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -89,6 +96,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x4b:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -97,6 +105,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x44:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -105,6 +114,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x46:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -113,6 +123,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x4a:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -121,6 +132,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x4c:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -129,6 +141,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x4e:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -137,6 +150,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x63:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -145,6 +159,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x67:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -153,6 +168,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x68:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -161,6 +177,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Curie chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nv50_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x84:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x86:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -57,6 +60,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x92:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -65,6 +69,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x94:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -73,6 +78,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x96:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -81,6 +87,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0x98:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -89,6 +96,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xa0:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -97,6 +105,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xaa:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -105,6 +114,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xac:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -113,6 +123,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xa3:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -121,6 +132,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xa5:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -129,6 +141,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xa8:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -137,6 +150,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xaf:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -145,6 +159,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Tesla chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nvc0_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xc4:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xc3:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -57,6 +60,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xce:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -65,6 +69,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xcf:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -73,6 +78,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xc1:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -81,6 +87,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xc8:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -89,6 +96,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xd9:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -97,6 +105,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Fermi chipset\n");
......
......@@ -29,6 +29,7 @@
#include <subdev/clock.h>
#include <subdev/devinit.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
int
nve0_identify(struct nouveau_device *device)
......@@ -41,6 +42,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
case 0xe7:
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -49,6 +51,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
break;
default:
nv_fatal(device, "unknown Kepler chipset\n");
......
/*
* 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 "subdev/timer.h"
bool
nouveau_timer_wait_eq(void *obj, u64 nsec, u32 addr, u32 mask, u32 data)
{
struct nouveau_timer *ptimer = nouveau_timer(obj);
u64 time0;
time0 = ptimer->read(ptimer);
do {
if (nv_iclass(obj, NV_SUBDEV_CLASS)) {
if ((nv_rd32(obj, addr) & mask) == data)
return true;
} else {
if ((nv_ro32(obj, addr) & mask) == data)
return true;
}
} while (ptimer->read(ptimer) - time0 < nsec);
return false;
}
bool
nouveau_timer_wait_ne(void *obj, u64 nsec, u32 addr, u32 mask, u32 data)
{
struct nouveau_timer *ptimer = nouveau_timer(obj);
u64 time0;
time0 = ptimer->read(ptimer);
do {
if (nv_iclass(obj, NV_SUBDEV_CLASS)) {
if ((nv_rd32(obj, addr) & mask) != data)
return true;
} else {
if ((nv_ro32(obj, addr) & mask) != data)
return true;
}
} while (ptimer->read(ptimer) - time0 < nsec);
return false;
}
bool
nouveau_timer_wait_cb(void *obj, u64 nsec, bool (*func)(void *), void *data)
{
struct nouveau_timer *ptimer = nouveau_timer(obj);
u64 time0;
time0 = ptimer->read(ptimer);
do {
if (func(data) == true)
return true;
} while (ptimer->read(ptimer) - time0 < nsec);
return false;
}
void
nouveau_timer_alarm(void *obj, u32 nsec, struct nouveau_alarm *alarm)
{
struct nouveau_timer *ptimer = nouveau_timer(obj);
ptimer->alarm(ptimer, nsec, alarm);
}
#include "drmP.h"
#include "drm.h"
#include "nouveau_drv.h"
#include <nouveau_drm.h>
#include "nouveau_hw.h"
int
nv04_timer_init(struct drm_device *dev)
/*
* 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 <subdev/timer.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;
};
static u64
nv04_timer_read(struct nouveau_timer *ptimer)
{
struct nv04_timer_priv *priv = (void *)ptimer;
u32 hi, lo;
do {
hi = nv_rd32(priv, NV04_PTIMER_TIME_1);
lo = nv_rd32(priv, NV04_PTIMER_TIME_0);
} while (hi != nv_rd32(priv, NV04_PTIMER_TIME_1));
return ((u64)hi << 32 | lo);
}
static void
nv04_timer_alarm_trigger(struct nouveau_timer *ptimer)
{
struct nv04_timer_priv *priv = (void *)ptimer;
struct nouveau_alarm *alarm, *atemp;
unsigned long flags;
LIST_HEAD(exec);
/* move any due alarms off the pending list */
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry_safe(alarm, atemp, &priv->alarms, head) {
if (alarm->timestamp <= ptimer->read(ptimer))
list_move_tail(&alarm->head, &exec);
}
/* reschedule interrupt for next alarm time */
if (!list_empty(&priv->alarms)) {
alarm = list_first_entry(&priv->alarms, typeof(*alarm), head);
nv_wr32(priv, NV04_PTIMER_ALARM_0, alarm->timestamp);
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000001);
} else {
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
}
spin_unlock_irqrestore(&priv->lock, flags);
/* execute any pending alarm handlers */
list_for_each_entry_safe(alarm, atemp, &exec, head) {
list_del(&alarm->head);
alarm->func(alarm);
}
}
static void
nv04_timer_alarm(struct nouveau_timer *ptimer, u32 time,
struct nouveau_alarm *alarm)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 m, n, d;
struct nv04_timer_priv *priv = (void *)ptimer;
struct nouveau_alarm *list;
unsigned long flags;
alarm->timestamp = ptimer->read(ptimer) + time;
/* append new alarm to list, in soonest-alarm-first order */
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry(list, &priv->alarms, head) {
if (list->timestamp > alarm->timestamp)
break;
}
list_add_tail(&alarm->head, &list->head);
spin_unlock_irqrestore(&priv->lock, flags);
nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
/* process pending alarms */
nv04_timer_alarm_trigger(ptimer);
}
static void
nv04_timer_intr(struct nouveau_subdev *subdev)
{
struct nv04_timer_priv *priv = (void *)subdev;
u32 stat = nv_rd32(priv, NV04_PTIMER_INTR_0);
if (stat & 0x00000001) {
nv04_timer_alarm_trigger(&priv->base);
nv_wr32(priv, NV04_PTIMER_INTR_0, 0x00000001);
stat &= ~0x00000001;
}
if (stat) {
nv_error(priv, "unknown stat 0x%08x\n", stat);
nv_wr32(priv, NV04_PTIMER_INTR_0, stat);
}
}
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;
INIT_LIST_HEAD(&priv->alarms);
spin_lock_init(&priv->lock);
return 0;
}
static void
nv04_timer_dtor(struct nouveau_object *object)
{
struct nv04_timer_priv *priv = (void *)object;
return nouveau_timer_destroy(&priv->base);
}
static int
nv04_timer_init(struct nouveau_object *object)
{
struct nouveau_device *device = nv_device(object);
struct nv04_timer_priv *priv = (void *)object;
u32 m = 1, f, n, d;
int ret;
ret = nouveau_timer_init(&priv->base);
if (ret)
return ret;
/* aim for 31.25MHz, which gives us nanosecond timestamps */
d = 1000000 / 32;
/* determine base clock for timer source */
if (dev_priv->chipset < 0x40) {
n = nouveau_hw_get_clock(dev, PLL_CORE);
#if 0 /*XXX*/
if (device->chipset < 0x40) {
n = nouveau_hw_get_clock(device, PLL_CORE);
} else
if (dev_priv->chipset == 0x40) {
#endif
if (device->chipset <= 0x40) {
/*XXX: figure this out */
f = -1;
n = 0;
} else {
n = dev_priv->crystal;
m = 1;
f = device->crystal;
n = f;
while (n < (d * 2)) {
n += (n / m);
m++;
}
nv_wr32(dev, 0x009220, m - 1);
nv_wr32(priv, 0x009220, m - 1);
}
if (!n) {
NV_WARN(dev, "PTIMER: unknown input clock freq\n");
if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
!nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1);
nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1);
nv_warn(priv, "unknown input clock freq\n");
if (!nv_rd32(priv, NV04_PTIMER_NUMERATOR) ||
!nv_rd32(priv, NV04_PTIMER_DENOMINATOR)) {
nv_wr32(priv, NV04_PTIMER_NUMERATOR, 1);
nv_wr32(priv, NV04_PTIMER_DENOMINATOR, 1);
}
return 0;
}
......@@ -60,25 +216,34 @@ nv04_timer_init(struct drm_device *dev)
d >>= 1;
}
nv_wr32(dev, NV04_PTIMER_NUMERATOR, n);
nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d);
nv_debug(priv, "input frequency : %dHz\n", f);
nv_debug(priv, "input multiplier: %d\n", m);
nv_debug(priv, "numerator : 0x%08x\n", n);
nv_debug(priv, "denominator : 0x%08x\n", d);
nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n);
nv_wr32(priv, NV04_PTIMER_NUMERATOR, n);
nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d);
nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff);
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
return 0;
}
u64
nv04_timer_read(struct drm_device *dev)
static int
nv04_timer_fini(struct nouveau_object *object, bool suspend)
{
u32 hi, lo;
do {
hi = nv_rd32(dev, NV04_PTIMER_TIME_1);
lo = nv_rd32(dev, NV04_PTIMER_TIME_0);
} while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1));
return ((u64)hi << 32 | lo);
struct nv04_timer_priv *priv = (void *)object;
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
return nouveau_timer_fini(&priv->base, suspend);
}
void
nv04_timer_takedown(struct drm_device *dev)
{
}
struct nouveau_oclass
nv04_timer_oclass = {
.handle = NV_SUBDEV(TIMER, 0x04),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv04_timer_ctor,
.dtor = nv04_timer_dtor,
.init = nv04_timer_init,
.fini = nv04_timer_fini,
}
};
......@@ -64,7 +64,7 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
getparam->value = 0; /* deprecated */
break;
case NOUVEAU_GETPARAM_PTIMER_TIME:
getparam->value = dev_priv->engine.timer.read(dev);
getparam->value = nv_timer_read(dev);
break;
case NOUVEAU_GETPARAM_HAS_BO_USAGE:
getparam->value = 1;
......
......@@ -9,6 +9,7 @@
#include <subdev/i2c.h>
#include <subdev/clock.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
void *nouveau_newpriv(struct drm_device *);
......@@ -300,5 +301,34 @@ nv_intr(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_mc *pmc = nouveau_mc(drm->device);
nv_subdev(pmc)->intr(pmc);
nv_subdev(pmc)->intr(&pmc->base);
}
bool nouveau_wait_eq(struct drm_device *dev, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_timer_wait_eq(drm->device, timeout, reg, mask, val);
}
bool nouveau_wait_ne(struct drm_device *dev, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_timer_wait_ne(drm->device, timeout, reg, mask, val);
}
bool nouveau_wait_cb(struct drm_device *dev, u64 timeout,
bool (*cond)(void *), void *data)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_timer_wait_cb(drm->device, timeout, cond, data);
}
u64
nv_timer_read(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_timer *ptimer = nouveau_timer(drm->device);
return ptimer->read(ptimer);
}
......@@ -53,4 +53,13 @@ void nouveau_bios_init_exec(struct drm_device *, u16);
void nv_intr(struct drm_device *);
bool nouveau_wait_eq(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
bool nouveau_wait_cb(struct drm_device *, u64 timeout,
bool (*cond)(void *), void *);
u64 nv_timer_read(struct drm_device *);
#endif
......@@ -252,7 +252,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
NV_INFO(dev, "Reinitialising engines...\n");
engine->instmem.resume(dev);
engine->timer.init(dev);
engine->fb.init(dev);
for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
if (dev_priv->eng[i])
......
......@@ -324,12 +324,6 @@ struct nouveau_instmem_engine {
void (*flush)(struct drm_device *);
};
struct nouveau_timer_engine {
int (*init)(struct drm_device *dev);
void (*takedown)(struct drm_device *dev);
uint64_t (*read)(struct drm_device *dev);
};
struct nouveau_fb_engine {
int num_tiles;
struct drm_mm tag_heap;
......@@ -539,7 +533,6 @@ struct nouveau_vram_engine {
struct nouveau_engine {
struct nouveau_instmem_engine instmem;
struct nouveau_timer_engine timer;
struct nouveau_fb_engine fb;
struct nouveau_display_engine display;
struct nouveau_pm_engine pm;
......@@ -836,12 +829,6 @@ extern int nouveau_load(struct drm_device *, unsigned long flags);
extern int nouveau_firstopen(struct drm_device *);
extern void nouveau_lastclose(struct drm_device *);
extern int nouveau_unload(struct drm_device *);
extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
extern bool nouveau_wait_cb(struct drm_device *, u64 timeout,
bool (*cond)(void *), void *);
extern bool nouveau_wait_for_idle(struct drm_device *);
extern int nouveau_card_init(struct drm_device *);
......@@ -1204,11 +1191,6 @@ extern void nvc0_instmem_takedown(struct drm_device *);
extern int nvc0_instmem_suspend(struct drm_device *);
extern void nvc0_instmem_resume(struct drm_device *);
/* nv04_timer.c */
extern int nv04_timer_init(struct drm_device *);
extern uint64_t nv04_timer_read(struct drm_device *);
extern void nv04_timer_takedown(struct drm_device *);
extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);
......
......@@ -194,8 +194,7 @@ nouveau_pm_trigger(struct drm_device *dev)
/* change perflvl, if necessary */
if (perflvl != pm->cur) {
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
u64 time0 = ptimer->read(dev);
u64 time0 = nv_timer_read(dev);
NV_INFO(dev, "setting performance level: %d", perflvl->id);
ret = nouveau_pm_perflvl_set(dev, perflvl);
......@@ -203,7 +202,7 @@ nouveau_pm_trigger(struct drm_device *dev)
NV_INFO(dev, "> reclocking failed: %d\n\n", ret);
NV_INFO(dev, "> reclocking took %lluns\n\n",
ptimer->read(dev) - time0);
nv_timer_read(dev) - time0);
}
}
......@@ -553,8 +552,6 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr,
char *buf)
{
struct drm_device *dev = dev_get_drvdata(d);
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
u32 cycles, cur, prev;
u64 start;
......@@ -565,7 +562,7 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr,
* When the fan spins, it changes the value of GPIO FAN_SENSE.
* We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation.
*/
start = ptimer->read(dev);
start = nv_timer_read(dev);
prev = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE);
cycles = 0;
do {
......@@ -576,7 +573,7 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr,
}
usleep_range(500, 1000); /* supports 0 < rpm < 7500 */
} while (ptimer->read(dev) - start < 250000000);
} while (nv_timer_read(dev) - start < 250000000);
/* interpolate to get rpm */
return sprintf(buf, "%i\n", cycles / 4 * 4 * 60);
......
......@@ -61,9 +61,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv04_instmem_map;
engine->instmem.unmap = nv04_instmem_unmap;
engine->instmem.flush = nv04_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv04_fb_init;
engine->fb.takedown = nv04_fb_takedown;
engine->display.early_init = nv04_display_early_init;
......@@ -89,9 +86,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv04_instmem_map;
engine->instmem.unmap = nv04_instmem_unmap;
engine->instmem.flush = nv04_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv10_fb_init;
engine->fb.takedown = nv10_fb_takedown;
engine->fb.init_tile_region = nv10_fb_init_tile_region;
......@@ -124,9 +118,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv04_instmem_map;
engine->instmem.unmap = nv04_instmem_unmap;
engine->instmem.flush = nv04_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv20_fb_init;
engine->fb.takedown = nv20_fb_takedown;
engine->fb.init_tile_region = nv20_fb_init_tile_region;
......@@ -155,9 +146,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv04_instmem_map;
engine->instmem.unmap = nv04_instmem_unmap;
engine->instmem.flush = nv04_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv30_fb_init;
engine->fb.takedown = nv30_fb_takedown;
engine->fb.init_tile_region = nv30_fb_init_tile_region;
......@@ -189,9 +177,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv04_instmem_map;
engine->instmem.unmap = nv04_instmem_unmap;
engine->instmem.flush = nv04_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv40_fb_init;
engine->fb.takedown = nv40_fb_takedown;
engine->fb.init_tile_region = nv30_fb_init_tile_region;
......@@ -231,9 +216,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.flush = nv50_instmem_flush;
else
engine->instmem.flush = nv84_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv50_fb_init;
engine->fb.takedown = nv50_fb_takedown;
engine->display.early_init = nv50_display_early_init;
......@@ -287,9 +269,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv50_instmem_map;
engine->instmem.unmap = nv50_instmem_unmap;
engine->instmem.flush = nv84_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nvc0_fb_init;
engine->fb.takedown = nvc0_fb_takedown;
engine->display.early_init = nv50_display_early_init;
......@@ -322,9 +301,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv50_instmem_map;
engine->instmem.unmap = nv50_instmem_unmap;
engine->instmem.flush = nv84_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nvc0_fb_init;
engine->fb.takedown = nvc0_fb_takedown;
engine->display.early_init = nouveau_stub_init;
......@@ -355,9 +331,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->instmem.map = nv50_instmem_map;
engine->instmem.unmap = nv50_instmem_unmap;
engine->instmem.flush = nv84_instmem_flush;
engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nvc0_fb_init;
engine->fb.takedown = nvc0_fb_takedown;
engine->display.early_init = nouveau_stub_init;
......@@ -515,15 +488,10 @@ nouveau_card_init(struct drm_device *dev)
nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
}
/* PTIMER */
ret = engine->timer.init(dev);
if (ret)
goto out_bios;
/* PFB */
ret = engine->fb.init(dev);
if (ret)
goto out_timer;
goto out_bios;
ret = engine->vram.init(dev);
if (ret)
......@@ -770,8 +738,6 @@ nouveau_card_init(struct drm_device *dev)
engine->vram.takedown(dev);
out_fb:
engine->fb.takedown(dev);
out_timer:
engine->timer.takedown(dev);
out_bios:
nouveau_bios_takedown(dev);
out_display_early:
......@@ -824,7 +790,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
engine->vram.takedown(dev);
engine->fb.takedown(dev);
engine->timer.takedown(dev);
nouveau_bios_takedown(dev);
engine->display.late_takedown(dev);
......@@ -1143,57 +1108,6 @@ int nouveau_unload(struct drm_device *dev)
return 0;
}
/* Wait until (value(reg) & mask) == val, up until timeout has hit */
bool
nouveau_wait_eq(struct drm_device *dev, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
uint64_t start = ptimer->read(dev);
do {
if ((nv_rd32(dev, reg) & mask) == val)
return true;
} while (ptimer->read(dev) - start < timeout);
return false;
}
/* Wait until (value(reg) & mask) != val, up until timeout has hit */
bool
nouveau_wait_ne(struct drm_device *dev, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
uint64_t start = ptimer->read(dev);
do {
if ((nv_rd32(dev, reg) & mask) != val)
return true;
} while (ptimer->read(dev) - start < timeout);
return false;
}
/* Wait until cond(data) == true, up until timeout has hit */
bool
nouveau_wait_cb(struct drm_device *dev, u64 timeout,
bool (*cond)(void *), void *data)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
u64 start = ptimer->read(dev);
do {
if (cond(data) == true)
return true;
} while (ptimer->read(dev) - start < timeout);
return false;
}
/* Waits for PGRAPH to go completely idle */
bool nouveau_wait_for_idle(struct drm_device *dev)
{
......
......@@ -114,7 +114,6 @@ int
nv04_pm_clocks_set(struct drm_device *dev, void *pre_state)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
struct nv04_pm_state *state = pre_state;
prog_pll(dev, &state->core);
......@@ -130,7 +129,9 @@ nv04_pm_clocks_set(struct drm_device *dev, void *pre_state)
}
}
#if 0 /*XXX*/
ptimer->init(dev);
#endif
kfree(state);
return 0;
......
......@@ -88,8 +88,6 @@ nv50_display_late_takedown(struct drm_device *dev)
int
nv50_display_sync(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
struct nv50_display *disp = nv50_display(dev);
struct nouveau_channel *evo = disp->master;
u64 start;
......@@ -107,11 +105,11 @@ nv50_display_sync(struct drm_device *dev)
nv_wo32(disp->ntfy, 0x000, 0x00000000);
FIRE_RING (evo);
start = ptimer->read(dev);
start = nv_timer_read(dev);
do {
if (nv_ro32(disp->ntfy, 0x000))
return 0;
} while (ptimer->read(dev) - start < 2000000000ULL);
} while (nv_timer_read(dev) - start < 2000000000ULL);
}
return -EBUSY;
......
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