drm/nouveau/pmu: rename from pwr (no binary change)

Switch to NVIDIA's name for the device.

The namespace of NVKM is being changed to nvkm_ instead of nouveau_,
which will be used for the DRM part of the driver.  This is being
done in order to make it very clear as to what part of the driver a
given symbol belongs to, and as a minor step towards splitting the
DRM driver out to be able to stand on its own (for virt).

Because there's already a large amount of churn here anyway, this is
as good a time as any to also switch to NVIDIA's device and chipset
naming to ease collaboration with them.

A comparison of objdump disassemblies proves no code changes.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2015-01-14 00:04:21 +10:00
commit ebb58dc2ef
44 changed files with 551 additions and 551 deletions

View file

@ -35,7 +35,7 @@ enum nv_subdev_type {
NVDEV_SUBDEV_INSTMEM,
NVDEV_SUBDEV_VM,
NVDEV_SUBDEV_BAR,
NVDEV_SUBDEV_PWR,
NVDEV_SUBDEV_PMU,
NVDEV_SUBDEV_VOLT,
NVDEV_SUBDEV_THERM,
NVDEV_SUBDEV_CLK,

View file

@ -0,0 +1,57 @@
#ifndef __NOUVEAU_PMU_H__
#define __NOUVEAU_PMU_H__
#include <core/subdev.h>
#include <core/device.h>
struct nouveau_pmu {
struct nouveau_subdev base;
struct {
u32 base;
u32 size;
} send;
struct {
u32 base;
u32 size;
struct work_struct work;
wait_queue_head_t wait;
u32 process;
u32 message;
u32 data[2];
} recv;
int (*message)(struct nouveau_pmu *, u32[2], u32, u32, u32, u32);
void (*pgob)(struct nouveau_pmu *, bool);
};
static inline struct nouveau_pmu *
nouveau_pmu(void *obj)
{
return (void *)nouveau_subdev(obj, NVDEV_SUBDEV_PMU);
}
extern struct nouveau_oclass *nva3_pmu_oclass;
extern struct nouveau_oclass *nvc0_pmu_oclass;
extern struct nouveau_oclass *nvd0_pmu_oclass;
extern struct nouveau_oclass *gk104_pmu_oclass;
extern struct nouveau_oclass *nv108_pmu_oclass;
extern struct nouveau_oclass *gk20a_pmu_oclass;
/* interface to MEMX process running on PMU */
struct nouveau_memx;
int nouveau_memx_init(struct nouveau_pmu *, struct nouveau_memx **);
int nouveau_memx_fini(struct nouveau_memx **, bool exec);
void nouveau_memx_wr32(struct nouveau_memx *, u32 addr, u32 data);
void nouveau_memx_wait(struct nouveau_memx *,
u32 addr, u32 mask, u32 data, u32 nsec);
void nouveau_memx_nsec(struct nouveau_memx *, u32 nsec);
void nouveau_memx_wait_vblank(struct nouveau_memx *);
void nouveau_memx_train(struct nouveau_memx *);
int nouveau_memx_train_result(struct nouveau_pmu *, u32 *, int);
void nouveau_memx_block(struct nouveau_memx *);
void nouveau_memx_unblock(struct nouveau_memx *);
#endif

View file

@ -222,7 +222,7 @@ static const u64 disable_map[] = {
[NVDEV_SUBDEV_BAR] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_VOLT] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_THERM] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_PWR] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_PMU] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_FUSE] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_ENGINE_PERFMON] = NV_DEVICE_V0_DISABLE_CORE,

View file

@ -39,7 +39,7 @@
#include <subdev/instmem.h>
#include <subdev/vm.h>
#include <subdev/bar.h>
#include <subdev/pwr.h>
#include <subdev/pmu.h>
#include <subdev/volt.h>
#include <engine/device.h>
@ -77,7 +77,7 @@ gm100_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nv108_pmu_oclass;
#if 0
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
@ -121,7 +121,7 @@ gm100_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nv108_pmu_oclass;
#if 0
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
#endif

View file

@ -37,7 +37,7 @@
#include <subdev/instmem.h>
#include <subdev/vm.h>
#include <subdev/bar.h>
#include <subdev/pwr.h>
#include <subdev/pmu.h>
#include <subdev/volt.h>
#include <engine/device.h>
@ -362,7 +362,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nva3_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
@ -393,7 +393,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nva3_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
@ -423,7 +423,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nva3_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
@ -453,7 +453,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nva3_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;

View file

@ -39,7 +39,7 @@
#include <subdev/instmem.h>
#include <subdev/vm.h>
#include <subdev/bar.h>
#include <subdev/pwr.h>
#include <subdev/pmu.h>
#include <subdev/volt.h>
#include <engine/device.h>
@ -77,7 +77,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -110,7 +110,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -143,7 +143,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -175,7 +175,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -208,7 +208,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -240,7 +240,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -272,7 +272,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvc0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
@ -305,7 +305,7 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvd0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;

View file

@ -39,7 +39,7 @@
#include <subdev/instmem.h>
#include <subdev/vm.h>
#include <subdev/bar.h>
#include <subdev/pwr.h>
#include <subdev/pmu.h>
#include <subdev/volt.h>
#include <engine/device.h>
@ -77,7 +77,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = gk104_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = gk104_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
@ -111,7 +111,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvd0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
@ -145,7 +145,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = gk104_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = gk104_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
@ -180,7 +180,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &gk20a_volt_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = gk20a_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = gk20a_pmu_oclass;
break;
case 0xf0:
device->cname = "GK110";
@ -201,7 +201,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvd0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
@ -235,7 +235,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nvd0_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
@ -269,7 +269,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nv108_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
@ -302,7 +302,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PMU ] = nv108_pmu_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;

View file

@ -22,7 +22,7 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include <subdev/pwr.h>
#include <subdev/pmu.h>
#include "nvc0.h"
#include "ctxnvc0.h"
@ -196,15 +196,15 @@ nve4_graph_init(struct nouveau_object *object)
{
struct nvc0_graph_oclass *oclass = (void *)object->oclass;
struct nvc0_graph_priv *priv = (void *)object;
struct nouveau_pwr *ppwr = nouveau_pwr(priv);
struct nouveau_pmu *pmu = nouveau_pmu(priv);
const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
u32 data[TPC_MAX / 8] = {};
u8 tpcnr[GPC_MAX];
int gpc, tpc, rop;
int ret, i;
if (ppwr)
ppwr->pgob(ppwr, false);
if (pmu)
pmu->pgob(pmu, false);
ret = nouveau_graph_init(&priv->base);
if (ret)

View file

@ -12,7 +12,7 @@ include $(src)/nvkm/subdev/instmem/Kbuild
include $(src)/nvkm/subdev/ltc/Kbuild
include $(src)/nvkm/subdev/mc/Kbuild
include $(src)/nvkm/subdev/mxm/Kbuild
include $(src)/nvkm/subdev/pwr/Kbuild
include $(src)/nvkm/subdev/pmu/Kbuild
include $(src)/nvkm/subdev/therm/Kbuild
include $(src)/nvkm/subdev/timer/Kbuild
include $(src)/nvkm/subdev/vm/Kbuild

View file

@ -1,7 +1,7 @@
#ifndef __NVKM_FBRAM_FUC_H__
#define __NVKM_FBRAM_FUC_H__
#include <subdev/pwr.h>
#include <subdev/pmu.h>
struct ramfuc {
struct nouveau_memx *memx;
@ -57,10 +57,10 @@ ramfuc_reg(u32 addr)
static inline int
ramfuc_init(struct ramfuc *ram, struct nouveau_fb *pfb)
{
struct nouveau_pwr *ppwr = nouveau_pwr(pfb);
struct nouveau_pmu *pmu = nouveau_pmu(pfb);
int ret;
ret = nouveau_memx_init(ppwr, &ram->memx);
ret = nouveau_memx_init(pmu, &ram->memx);
if (ret)
return ret;
@ -149,9 +149,9 @@ ramfuc_train(struct ramfuc *ram)
static inline int
ramfuc_train_result(struct nouveau_fb *pfb, u32 *result, u32 rsize)
{
struct nouveau_pwr *ppwr = nouveau_pwr(pfb);
struct nouveau_pmu *pmu = nouveau_pmu(pfb);
return nouveau_memx_train_result(ppwr, result, rsize);
return nouveau_memx_train_result(pmu, result, rsize);
}
static inline void

View file

@ -33,7 +33,7 @@ nv98_mc_intr[] = {
{ 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */
{ 0x00008000, NVDEV_ENGINE_BSP },
{ 0x00020000, NVDEV_ENGINE_VP },
{ 0x00040000, NVDEV_SUBDEV_PWR }, /* NVA3:NVC0 */
{ 0x00040000, NVDEV_SUBDEV_PMU }, /* NVA3:NVC0 */
{ 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */
{ 0x00100000, NVDEV_SUBDEV_TIMER },
{ 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */

View file

@ -40,7 +40,7 @@ nvc0_mc_intr[] = {
{ 0x00100000, NVDEV_SUBDEV_TIMER },
{ 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */
{ 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */
{ 0x01000000, NVDEV_SUBDEV_PWR },
{ 0x01000000, NVDEV_SUBDEV_PMU },
{ 0x02000000, NVDEV_SUBDEV_LTC },
{ 0x08000000, NVDEV_SUBDEV_FB },
{ 0x10000000, NVDEV_SUBDEV_BUS },

View file

@ -0,0 +1,8 @@
nvkm-y += nvkm/subdev/pmu/base.o
nvkm-y += nvkm/subdev/pmu/memx.o
nvkm-y += nvkm/subdev/pmu/nva3.o
nvkm-y += nvkm/subdev/pmu/nvc0.o
nvkm-y += nvkm/subdev/pmu/nvd0.o
nvkm-y += nvkm/subdev/pmu/gk104.o
nvkm-y += nvkm/subdev/pmu/nv108.o
nvkm-y += nvkm/subdev/pmu/gk20a.o

View file

@ -0,0 +1,272 @@
/*
* Copyright 2013 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>
#include "priv.h"
void
nouveau_pmu_pgob(struct nouveau_pmu *pmu, bool enable)
{
const struct nvkm_pmu_impl *impl = (void *)nv_oclass(pmu);
if (impl->pgob)
impl->pgob(pmu, enable);
}
static int
nouveau_pmu_send(struct nouveau_pmu *pmu, u32 reply[2],
u32 process, u32 message, u32 data0, u32 data1)
{
struct nouveau_subdev *subdev = nv_subdev(pmu);
u32 addr;
/* wait for a free slot in the fifo */
addr = nv_rd32(pmu, 0x10a4a0);
if (!nv_wait_ne(pmu, 0x10a4b0, 0xffffffff, addr ^ 8))
return -EBUSY;
/* we currently only support a single process at a time waiting
* on a synchronous reply, take the PMU mutex and tell the
* receive handler what we're waiting for
*/
if (reply) {
mutex_lock(&subdev->mutex);
pmu->recv.message = message;
pmu->recv.process = process;
}
/* acquire data segment access */
do {
nv_wr32(pmu, 0x10a580, 0x00000001);
} while (nv_rd32(pmu, 0x10a580) != 0x00000001);
/* write the packet */
nv_wr32(pmu, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
pmu->send.base));
nv_wr32(pmu, 0x10a1c4, process);
nv_wr32(pmu, 0x10a1c4, message);
nv_wr32(pmu, 0x10a1c4, data0);
nv_wr32(pmu, 0x10a1c4, data1);
nv_wr32(pmu, 0x10a4a0, (addr + 1) & 0x0f);
/* release data segment access */
nv_wr32(pmu, 0x10a580, 0x00000000);
/* wait for reply, if requested */
if (reply) {
wait_event(pmu->recv.wait, (pmu->recv.process == 0));
reply[0] = pmu->recv.data[0];
reply[1] = pmu->recv.data[1];
mutex_unlock(&subdev->mutex);
}
return 0;
}
static void
nouveau_pmu_recv(struct work_struct *work)
{
struct nouveau_pmu *pmu =
container_of(work, struct nouveau_pmu, recv.work);
u32 process, message, data0, data1;
/* nothing to do if GET == PUT */
u32 addr = nv_rd32(pmu, 0x10a4cc);
if (addr == nv_rd32(pmu, 0x10a4c8))
return;
/* acquire data segment access */
do {
nv_wr32(pmu, 0x10a580, 0x00000002);
} while (nv_rd32(pmu, 0x10a580) != 0x00000002);
/* read the packet */
nv_wr32(pmu, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
pmu->recv.base));
process = nv_rd32(pmu, 0x10a1c4);
message = nv_rd32(pmu, 0x10a1c4);
data0 = nv_rd32(pmu, 0x10a1c4);
data1 = nv_rd32(pmu, 0x10a1c4);
nv_wr32(pmu, 0x10a4cc, (addr + 1) & 0x0f);
/* release data segment access */
nv_wr32(pmu, 0x10a580, 0x00000000);
/* wake process if it's waiting on a synchronous reply */
if (pmu->recv.process) {
if (process == pmu->recv.process &&
message == pmu->recv.message) {
pmu->recv.data[0] = data0;
pmu->recv.data[1] = data1;
pmu->recv.process = 0;
wake_up(&pmu->recv.wait);
return;
}
}
/* right now there's no other expected responses from the engine,
* so assume that any unexpected message is an error.
*/
nv_warn(pmu, "%c%c%c%c 0x%08x 0x%08x 0x%08x 0x%08x\n",
(char)((process & 0x000000ff) >> 0),
(char)((process & 0x0000ff00) >> 8),
(char)((process & 0x00ff0000) >> 16),
(char)((process & 0xff000000) >> 24),
process, message, data0, data1);
}
static void
nouveau_pmu_intr(struct nouveau_subdev *subdev)
{
struct nouveau_pmu *pmu = (void *)subdev;
u32 disp = nv_rd32(pmu, 0x10a01c);
u32 intr = nv_rd32(pmu, 0x10a008) & disp & ~(disp >> 16);
if (intr & 0x00000020) {
u32 stat = nv_rd32(pmu, 0x10a16c);
if (stat & 0x80000000) {
nv_error(pmu, "UAS fault at 0x%06x addr 0x%08x\n",
stat & 0x00ffffff, nv_rd32(pmu, 0x10a168));
nv_wr32(pmu, 0x10a16c, 0x00000000);
intr &= ~0x00000020;
}
}
if (intr & 0x00000040) {
schedule_work(&pmu->recv.work);
nv_wr32(pmu, 0x10a004, 0x00000040);
intr &= ~0x00000040;
}
if (intr & 0x00000080) {
nv_info(pmu, "wr32 0x%06x 0x%08x\n", nv_rd32(pmu, 0x10a7a0),
nv_rd32(pmu, 0x10a7a4));
nv_wr32(pmu, 0x10a004, 0x00000080);
intr &= ~0x00000080;
}
if (intr) {
nv_error(pmu, "intr 0x%08x\n", intr);
nv_wr32(pmu, 0x10a004, intr);
}
}
int
_nouveau_pmu_fini(struct nouveau_object *object, bool suspend)
{
struct nouveau_pmu *pmu = (void *)object;
nv_wr32(pmu, 0x10a014, 0x00000060);
flush_work(&pmu->recv.work);
return nouveau_subdev_fini(&pmu->base, suspend);
}
int
_nouveau_pmu_init(struct nouveau_object *object)
{
const struct nvkm_pmu_impl *impl = (void *)object->oclass;
struct nouveau_pmu *pmu = (void *)object;
int ret, i;
ret = nouveau_subdev_init(&pmu->base);
if (ret)
return ret;
nv_subdev(pmu)->intr = nouveau_pmu_intr;
pmu->message = nouveau_pmu_send;
pmu->pgob = nouveau_pmu_pgob;
/* prevent previous ucode from running, wait for idle, reset */
nv_wr32(pmu, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */
nv_wait(pmu, 0x10a04c, 0xffffffff, 0x00000000);
nv_mask(pmu, 0x000200, 0x00002000, 0x00000000);
nv_mask(pmu, 0x000200, 0x00002000, 0x00002000);
nv_rd32(pmu, 0x000200);
nv_wait(pmu, 0x10a10c, 0x00000006, 0x00000000);
/* upload data segment */
nv_wr32(pmu, 0x10a1c0, 0x01000000);
for (i = 0; i < impl->data.size / 4; i++)
nv_wr32(pmu, 0x10a1c4, impl->data.data[i]);
/* upload code segment */
nv_wr32(pmu, 0x10a180, 0x01000000);
for (i = 0; i < impl->code.size / 4; i++) {
if ((i & 0x3f) == 0)
nv_wr32(pmu, 0x10a188, i >> 6);
nv_wr32(pmu, 0x10a184, impl->code.data[i]);
}
/* start it running */
nv_wr32(pmu, 0x10a10c, 0x00000000);
nv_wr32(pmu, 0x10a104, 0x00000000);
nv_wr32(pmu, 0x10a100, 0x00000002);
/* wait for valid host->pmu ring configuration */
if (!nv_wait_ne(pmu, 0x10a4d0, 0xffffffff, 0x00000000))
return -EBUSY;
pmu->send.base = nv_rd32(pmu, 0x10a4d0) & 0x0000ffff;
pmu->send.size = nv_rd32(pmu, 0x10a4d0) >> 16;
/* wait for valid pmu->host ring configuration */
if (!nv_wait_ne(pmu, 0x10a4dc, 0xffffffff, 0x00000000))
return -EBUSY;
pmu->recv.base = nv_rd32(pmu, 0x10a4dc) & 0x0000ffff;
pmu->recv.size = nv_rd32(pmu, 0x10a4dc) >> 16;
nv_wr32(pmu, 0x10a010, 0x000000e0);
return 0;
}
int
nouveau_pmu_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, int length, void **pobject)
{
struct nouveau_pmu *pmu;
int ret;
ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PMU",
"pmu", length, pobject);
pmu = *pobject;
if (ret)
return ret;
INIT_WORK(&pmu->recv.work, nouveau_pmu_recv);
init_waitqueue_head(&pmu->recv.wait);
return 0;
}
int
_nouveau_pmu_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nouveau_pmu *pmu;
int ret = nouveau_pmu_create(parent, engine, oclass, &pmu);
*pobject = nv_object(pmu);
return ret;
}

View file

@ -0,0 +1,94 @@
/*
* Copyright 2014 Martin Peres <martin.peres@free.fr>
*
* 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 folloing 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: Martin Peres
*/
/******************************************************************************
* arith data segment
*****************************************************************************/
#ifdef INCLUDE_PROC
#endif
#ifdef INCLUDE_DATA
#endif
/******************************************************************************
* arith code segment
*****************************************************************************/
#ifdef INCLUDE_CODE
// does a 32x32 -> 64 multiplication
//
// A * B = A_lo * B_lo
// + ( A_hi * B_lo ) << 16
// + ( A_lo * B_hi ) << 16
// + ( A_hi * B_hi ) << 32
//
// $r15 - current
// $r14 - A
// $r13 - B
// $r12 - mul_lo (return)
// $r11 - mul_hi (return)
// $r0 - zero
mulu32_32_64:
push $r1 // A_hi
push $r2 // B_hi
push $r3 // tmp0
push $r4 // tmp1
shr b32 $r1 $r14 16
shr b32 $r2 $r13 16
clear b32 $r12
clear b32 $r11
// A_lo * B_lo
mulu $r12 $r14 $r13
// ( A_hi * B_lo ) << 16
mulu $r3 $r1 $r13 // tmp0 = A_hi * B_lo
mov b32 $r4 $r3
and $r3 0xffff // tmp0 = tmp0_lo
shl b32 $r3 16
shr b32 $r4 16 // tmp1 = tmp0_hi
add b32 $r12 $r3
adc b32 $r11 $r4
// ( A_lo * B_hi ) << 16
mulu $r3 $r14 $r2 // tmp0 = A_lo * B_hi
mov b32 $r4 $r3
and $r3 0xffff // tmp0 = tmp0_lo
shl b32 $r3 16
shr b32 $r4 16 // tmp1 = tmp0_hi
add b32 $r12 $r3
adc b32 $r11 $r4
// ( A_hi * B_hi ) << 32
mulu $r3 $r1 $r2 // tmp0 = A_hi * B_hi
add b32 $r11 $r3
pop $r4
pop $r3
pop $r2
pop $r1
ret
#endif

View file

@ -0,0 +1,151 @@
/*
* Copyright 2013 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
*/
#ifdef INCLUDE_PROC
process(PROC_HOST, #host_init, #host_recv)
#endif
/******************************************************************************
* HOST data segment
*****************************************************************************/
#ifdef INCLUDE_DATA
// HOST (R)FIFO packet format
.equ #fifo_process 0x00
.equ #fifo_message 0x04
.equ #fifo_data0 0x08
.equ #fifo_data1 0x0c
// HOST HOST->PWR queue description
.equ #fifo_qlen 4 // log2(size of queue entry in bytes)
.equ #fifo_qnum 3 // log2(max number of entries in queue)
.equ #fifo_qmaskb (1 << #fifo_qnum) // max number of entries in queue
.equ #fifo_qmaskp (#fifo_qmaskb - 1)
.equ #fifo_qmaskf ((#fifo_qmaskb << 1) - 1)
.equ #fifo_qsize (1 << (#fifo_qlen + #fifo_qnum))
fifo_queue: .skip 128 // #fifo_qsize
// HOST PWR->HOST queue description
.equ #rfifo_qlen 4 // log2(size of queue entry in bytes)
.equ #rfifo_qnum 3 // log2(max number of entries in queue)
.equ #rfifo_qmaskb (1 << #rfifo_qnum) // max number of entries in queue
.equ #rfifo_qmaskp (#rfifo_qmaskb - 1)
.equ #rfifo_qmaskf ((#rfifo_qmaskb << 1) - 1)
.equ #rfifo_qsize (1 << (#rfifo_qlen + #rfifo_qnum))
rfifo_queue: .skip 128 // #rfifo_qsize
#endif
/******************************************************************************
* HOST code segment
*****************************************************************************/
#ifdef INCLUDE_CODE
// HOST->PWR comms - dequeue message(s) for process(es) from FIFO
//
// $r15 - current (host)
// $r0 - zero
host_send:
nv_iord($r1, NV_PPWR_FIFO_GET(0))
nv_iord($r2, NV_PPWR_FIFO_PUT(0))
cmp b32 $r1 $r2
bra e #host_send_done
// calculate address of message
and $r14 $r1 #fifo_qmaskp
shl b32 $r14 $r14 #fifo_qlen
add b32 $r14 #fifo_queue
// read message data, and pass to appropriate process
ld b32 $r11 D[$r14 + #fifo_data1]
ld b32 $r12 D[$r14 + #fifo_data0]
ld b32 $r13 D[$r14 + #fifo_message]
ld b32 $r14 D[$r14 + #fifo_process]
call(send)
// increment GET
add b32 $r1 0x1
and $r14 $r1 #fifo_qmaskf
nv_iowr(NV_PPWR_FIFO_GET(0), $r14)
bra #host_send
host_send_done:
ret
// PWR->HOST comms - enqueue message for HOST to RFIFO
//
// $r15 - current (host)
// $r14 - process
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0 - zero
host_recv:
// message from intr handler == HOST->PWR comms pending
mov $r1 (PROC_KERN & 0x0000ffff)
sethi $r1 (PROC_KERN & 0xffff0000)
cmp b32 $r14 $r1
bra e #host_send
// wait for space in RFIFO
host_recv_wait:
nv_iord($r1, NV_PPWR_RFIFO_GET)
nv_iord($r2, NV_PPWR_RFIFO_PUT)
xor $r1 #rfifo_qmaskb
cmp b32 $r1 $r2
bra e #host_recv_wait
and $r3 $r2 #rfifo_qmaskp
shl b32 $r3 #rfifo_qlen
add b32 $r3 #rfifo_queue
// enqueue message
st b32 D[$r3 + #fifo_data1] $r11
st b32 D[$r3 + #fifo_data0] $r12
st b32 D[$r3 + #fifo_message] $r13
st b32 D[$r3 + #fifo_process] $r14
add b32 $r2 0x1
and $r2 #rfifo_qmaskf
nv_iowr(NV_PPWR_RFIFO_PUT, $r2)
// notify host of pending message
mov $r2 NV_PPWR_INTR_TRIGGER_USER0
nv_iowr(NV_PPWR_INTR_TRIGGER, $r2)
ret
// $r15 - current (host)
// $r0 - zero
host_init:
// store each fifo's base/size in H2D/D2H scratch regs
mov $r1 #fifo_qsize
shl b32 $r1 16
or $r1 #fifo_queue
nv_iowr(NV_PPWR_H2D, $r1);
mov $r1 #rfifo_qsize
shl b32 $r1 16
or $r1 #rfifo_queue
nv_iowr(NV_PPWR_D2H, $r1);
// enable fifo subintr for first fifo
mov $r1 1
nv_iowr(NV_PPWR_FIFO_INTR_EN, $r1)
ret
#endif

View file

@ -0,0 +1,393 @@
/*
* Copyright 2013 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
*/
#define T_TIMEOUT 2200000
#define T_RISEFALL 1000
#define T_HOLD 5000
#ifdef INCLUDE_PROC
process(PROC_I2C_, #i2c_init, #i2c_recv)
#endif
/******************************************************************************
* I2C_ data segment
*****************************************************************************/
#ifdef INCLUDE_DATA
i2c_scl_map:
.b32 NV_PPWR_OUTPUT_I2C_0_SCL
.b32 NV_PPWR_OUTPUT_I2C_1_SCL
.b32 NV_PPWR_OUTPUT_I2C_2_SCL
.b32 NV_PPWR_OUTPUT_I2C_3_SCL
.b32 NV_PPWR_OUTPUT_I2C_4_SCL
.b32 NV_PPWR_OUTPUT_I2C_5_SCL
.b32 NV_PPWR_OUTPUT_I2C_6_SCL
.b32 NV_PPWR_OUTPUT_I2C_7_SCL
.b32 NV_PPWR_OUTPUT_I2C_8_SCL
.b32 NV_PPWR_OUTPUT_I2C_9_SCL
i2c_sda_map:
.b32 NV_PPWR_OUTPUT_I2C_0_SDA
.b32 NV_PPWR_OUTPUT_I2C_1_SDA
.b32 NV_PPWR_OUTPUT_I2C_2_SDA
.b32 NV_PPWR_OUTPUT_I2C_3_SDA
.b32 NV_PPWR_OUTPUT_I2C_4_SDA
.b32 NV_PPWR_OUTPUT_I2C_5_SDA
.b32 NV_PPWR_OUTPUT_I2C_6_SDA
.b32 NV_PPWR_OUTPUT_I2C_7_SDA
.b32 NV_PPWR_OUTPUT_I2C_8_SDA
.b32 NV_PPWR_OUTPUT_I2C_9_SDA
#if NVKM_PPWR_CHIPSET < GF119
i2c_ctrl:
.b32 0x00e138
.b32 0x00e150
.b32 0x00e168
.b32 0x00e180
.b32 0x00e254
.b32 0x00e274
.b32 0x00e764
.b32 0x00e780
.b32 0x00e79c
.b32 0x00e7b8
#endif
#endif
/******************************************************************************
* I2C_ code segment
*****************************************************************************/
#ifdef INCLUDE_CODE
// $r3 - value
// $r2 - sda line
// $r1 - scl line
// $r0 - zero
i2c_drive_scl:
cmp b32 $r3 0
bra e #i2c_drive_scl_lo
nv_iowr(NV_PPWR_OUTPUT_SET, $r1)
ret
i2c_drive_scl_lo:
nv_iowr(NV_PPWR_OUTPUT_CLR, $r1)
ret
i2c_drive_sda:
cmp b32 $r3 0
bra e #i2c_drive_sda_lo
nv_iowr(NV_PPWR_OUTPUT_SET, $r2)
ret
i2c_drive_sda_lo:
nv_iowr(NV_PPWR_OUTPUT_CLR, $r2)
ret
i2c_sense_scl:
bclr $flags $p1
nv_iord($r3, NV_PPWR_INPUT)
and $r3 $r1
bra z #i2c_sense_scl_done
bset $flags $p1
i2c_sense_scl_done:
ret
i2c_sense_sda:
bclr $flags $p1
nv_iord($r3, NV_PPWR_INPUT)
and $r3 $r2
bra z #i2c_sense_sda_done
bset $flags $p1
i2c_sense_sda_done:
ret
#define i2c_drive_scl(v) /*
*/ mov $r3 (v) /*
*/ call(i2c_drive_scl)
#define i2c_drive_sda(v) /*
*/ mov $r3 (v) /*
*/ call(i2c_drive_sda)
#define i2c_sense_scl() /*
*/ call(i2c_sense_scl)
#define i2c_sense_sda() /*
*/ call(i2c_sense_sda)
#define i2c_delay(v) /*
*/ mov $r14 (v) /*
*/ call(nsec)
#define i2c_trace_init() /*
*/ imm32($r6, 0x10000000) /*
*/ sub b32 $r7 $r6 1 /*
*/
#define i2c_trace_down() /*
*/ shr b32 $r6 4 /*
*/ push $r5 /*
*/ shl b32 $r5 $r6 4 /*
*/ sub b32 $r5 $r6 /*
*/ not b32 $r5 /*
*/ and $r7 $r5 /*
*/ pop $r5 /*
*/
#define i2c_trace_exit() /*
*/ shl b32 $r6 4 /*
*/
#define i2c_trace_next() /*
*/ add b32 $r7 $r6 /*
*/
#define i2c_trace_call(func) /*
*/ i2c_trace_next() /*
*/ i2c_trace_down() /*
*/ call(func) /*
*/ i2c_trace_exit() /*
*/
i2c_raise_scl:
push $r4
mov $r4 (T_TIMEOUT / T_RISEFALL)
i2c_drive_scl(1)
i2c_raise_scl_wait:
i2c_delay(T_RISEFALL)
i2c_sense_scl()
bra $p1 #i2c_raise_scl_done
sub b32 $r4 1
bra nz #i2c_raise_scl_wait
i2c_raise_scl_done:
pop $r4
ret
i2c_start:
i2c_sense_scl()
bra not $p1 #i2c_start_rep
i2c_sense_sda()
bra not $p1 #i2c_start_rep
bra #i2c_start_send
i2c_start_rep:
i2c_drive_scl(0)
i2c_drive_sda(1)
i2c_trace_call(i2c_raise_scl)
bra not $p1 #i2c_start_out
i2c_start_send:
i2c_drive_sda(0)
i2c_delay(T_HOLD)
i2c_drive_scl(0)
i2c_delay(T_HOLD)
i2c_start_out:
ret
i2c_stop:
i2c_drive_scl(0)
i2c_drive_sda(0)
i2c_delay(T_RISEFALL)
i2c_drive_scl(1)
i2c_delay(T_HOLD)
i2c_drive_sda(1)
i2c_delay(T_HOLD)
ret
// $r3 - value
// $r2 - sda line
// $r1 - scl line
// $r0 - zero
i2c_bitw:
call(i2c_drive_sda)
i2c_delay(T_RISEFALL)
i2c_trace_call(i2c_raise_scl)
bra not $p1 #i2c_bitw_out
i2c_delay(T_HOLD)
i2c_drive_scl(0)
i2c_delay(T_HOLD)
i2c_bitw_out:
ret
// $r3 - value (out)
// $r2 - sda line
// $r1 - scl line
// $r0 - zero
i2c_bitr:
i2c_drive_sda(1)
i2c_delay(T_RISEFALL)
i2c_trace_call(i2c_raise_scl)
bra not $p1 #i2c_bitr_done
i2c_sense_sda()
i2c_drive_scl(0)
i2c_delay(T_HOLD)
xbit $r3 $flags $p1
bset $flags $p1
i2c_bitr_done:
ret
i2c_get_byte:
mov $r5 0
mov $r4 8
i2c_get_byte_next:
shl b32 $r5 1
i2c_trace_call(i2c_bitr)
bra not $p1 #i2c_get_byte_done
or $r5 $r3
sub b32 $r4 1
bra nz #i2c_get_byte_next
mov $r3 1
i2c_trace_call(i2c_bitw)
i2c_get_byte_done:
ret
i2c_put_byte:
mov $r4 8
i2c_put_byte_next:
sub b32 $r4 1
xbit $r3 $r5 $r4
i2c_trace_call(i2c_bitw)
bra not $p1 #i2c_put_byte_done
cmp b32 $r4 0
bra ne #i2c_put_byte_next
i2c_trace_call(i2c_bitr)
bra not $p1 #i2c_put_byte_done
i2c_trace_next()
cmp b32 $r3 1
bra ne #i2c_put_byte_done
bclr $flags $p1 // nack
i2c_put_byte_done:
ret
i2c_addr:
i2c_trace_call(i2c_start)
bra not $p1 #i2c_addr_done
extr $r3 $r12 I2C__MSG_DATA0_ADDR
shl b32 $r3 1
or $r5 $r3
i2c_trace_call(i2c_put_byte)
i2c_addr_done:
ret
i2c_acquire_addr:
extr $r14 $r12 I2C__MSG_DATA0_PORT
#if NVKM_PPWR_CHIPSET < GF119
shl b32 $r14 2
add b32 $r14 #i2c_ctrl
ld b32 $r14 D[$r14]
#else
shl b32 $r14 5
add b32 $r14 0x00d014
#endif
ret
i2c_acquire:
call(i2c_acquire_addr)
call(rd32)
bset $r13 3
call(wr32)
ret
i2c_release:
call(i2c_acquire_addr)
call(rd32)
bclr $r13 3
call(wr32)
ret
// description
//
// $r15 - current (i2c)
// $r14 - sender process name
// $r13 - message
// $r12 - data0
// $r11 - data1
// $r0 - zero
i2c_recv:
bclr $flags $p1
extr $r1 $r12 I2C__MSG_DATA0_PORT
shl b32 $r1 2
cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map)
bra ge #i2c_recv_done
add b32 $r3 $r1 #i2c_sda_map
ld b32 $r2 D[$r3]
add b32 $r3 $r1 #i2c_scl_map
ld b32 $r1 D[$r3]
bset $flags $p2
push $r13
push $r14
push $r13
i2c_trace_init()
i2c_trace_call(i2c_acquire)
pop $r13
cmp b32 $r13 I2C__MSG_RD08
bra ne #i2c_recv_not_rd08
mov $r5 0
i2c_trace_call(i2c_addr)
bra not $p1 #i2c_recv_done
extr $r5 $r12 I2C__MSG_DATA0_RD08_REG
i2c_trace_call(i2c_put_byte)
bra not $p1 #i2c_recv_done
mov $r5 1
i2c_trace_call(i2c_addr)
bra not $p1 #i2c_recv_done
i2c_trace_call(i2c_get_byte)
bra not $p1 #i2c_recv_done
ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL
i2c_trace_call(i2c_stop)
mov b32 $r11 $r5
clear b32 $r7
bra #i2c_recv_done
i2c_recv_not_rd08:
cmp b32 $r13 I2C__MSG_WR08
bra ne #i2c_recv_not_wr08
mov $r5 0
call(i2c_addr)
bra not $p1 #i2c_recv_done
extr $r5 $r12 I2C__MSG_DATA0_WR08_REG
call(i2c_put_byte)
bra not $p1 #i2c_recv_done
mov $r5 0
call(i2c_addr)
bra not $p1 #i2c_recv_done
extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL
call(i2c_put_byte)
bra not $p1 #i2c_recv_done
call(i2c_stop)
clear b32 $r7
extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC
bra nz #i2c_recv_done
bclr $flags $p2
bra #i2c_recv_done
i2c_recv_not_wr08:
i2c_recv_done:
extr $r14 $r12 I2C__MSG_DATA0_PORT
call(i2c_release)
pop $r14
pop $r13
bra not $p2 #i2c_recv_exit
mov b32 $r12 $r7
call(send)
i2c_recv_exit:
ret
// description
//
// $r15 - current (i2c)
// $r0 - zero
i2c_init:
ret
#endif

View file

@ -0,0 +1,84 @@
/*
* Copyright 2013 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
*/
#ifdef INCLUDE_PROC
process(PROC_IDLE, #idle, #idle_recv)
#endif
/******************************************************************************
* IDLE data segment
*****************************************************************************/
#ifdef INCLUDE_DATA
#endif
/******************************************************************************
* IDLE code segment
*****************************************************************************/
#ifdef INCLUDE_CODE
// description
//
// $r15 - current (idle)
// $r14 - message
// $r0 - zero
idle_recv:
ret
// description
//
// $r15 - current (idle)
// $r0 - zero
idle:
// set our "no interrupt has occurred during our execution" flag
bset $flags $p0
// count IDLE invocations for debugging purposes
nv_iord($r1, NV_PPWR_DSCRATCH(1))
add b32 $r1 1
nv_iowr(NV_PPWR_DSCRATCH(1), $r1)
// keep looping while there's pending messages for any process
idle_loop:
mov $r1 #proc_list_head
bclr $flags $p2
idle_proc:
// process the process' messages until there's none left
idle_proc_exec:
push $r1
mov b32 $r14 $r1
call(recv)
pop $r1
bra not $p1 #idle_proc_next
bset $flags $p2
bra #idle_proc_exec
// next process!
idle_proc_next:
add b32 $r1 #proc_size
cmp b32 $r1 $r15
bra ne #idle_proc
bra $p2 #idle_loop
// sleep if no interrupts have occurred
sleep $p0
bra #idle
#endif

View file

@ -0,0 +1,556 @@
/*
* Copyright 2013 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
*/
/******************************************************************************
* kernel data segment
*****************************************************************************/
#ifdef INCLUDE_PROC
proc_kern:
process(PROC_KERN, 0, 0)
proc_list_head:
#endif
#ifdef INCLUDE_DATA
proc_list_tail:
time_prev: .b32 0
time_next: .b32 0
#endif
/******************************************************************************
* kernel code segment
*****************************************************************************/
#ifdef INCLUDE_CODE
bra #init
// read nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data (return)
// $r0 - zero
rd32:
nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
rd32_wait:
nv_iord($r13, NV_PPWR_MMIO_CTRL)
and $r13 NV_PPWR_MMIO_CTRL_STATUS
bra nz #rd32_wait
nv_iord($r13, NV_PPWR_MMIO_DATA)
ret
// write nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data
// $r0 - zero
wr32:
nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
nv_iowr(NV_PPWR_MMIO_DATA, $r13)
mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
#ifdef NVKM_FALCON_MMIO_TRAP
push $r13
mov $r13 NV_PPWR_INTR_TRIGGER_USER1
nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
wr32_host:
nv_iord($r13, NV_PPWR_INTR)
and $r13 NV_PPWR_INTR_USER1
bra nz #wr32_host
pop $r13
#endif
nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
wr32_wait:
nv_iord($r13, NV_PPWR_MMIO_CTRL)
and $r13 NV_PPWR_MMIO_CTRL_STATUS
bra nz #wr32_wait
ret
// busy-wait for a period of time
//
// $r15 - current
// $r14 - ns
// $r0 - zero
nsec:
push $r9
push $r8
nv_iord($r8, NV_PPWR_TIMER_LOW)
nsec_loop:
nv_iord($r9, NV_PPWR_TIMER_LOW)
sub b32 $r9 $r8
cmp b32 $r9 $r14
bra l #nsec_loop
pop $r8
pop $r9
ret
// busy-wait for a period of time
//
// $r15 - current
// $r14 - addr
// $r13 - mask
// $r12 - data
// $r11 - timeout (ns)
// $r0 - zero
wait:
push $r9
push $r8
nv_iord($r8, NV_PPWR_TIMER_LOW)
wait_loop:
nv_rd32($r10, $r14)
and $r10 $r13
cmp b32 $r10 $r12
bra e #wait_done
nv_iord($r9, NV_PPWR_TIMER_LOW)
sub b32 $r9 $r8
cmp b32 $r9 $r11
bra l #wait_loop
wait_done:
pop $r8
pop $r9
ret
// $r15 - current (kern)
// $r14 - process
// $r8 - NV_PPWR_INTR
intr_watchdog:
// read process' timer status, skip if not enabled
ld b32 $r9 D[$r14 + #proc_time]
cmp b32 $r9 0
bra z #intr_watchdog_next_proc
// subtract last timer's value from process' timer,
// if it's <= 0 then the timer has expired
ld b32 $r10 D[$r0 + #time_prev]
sub b32 $r9 $r10
bra g #intr_watchdog_next_time
mov $r13 KMSG_ALARM
call(send_proc)
clear b32 $r9
bra #intr_watchdog_next_proc
// otherwise, update the next timer's value if this
// process' timer is the soonest
intr_watchdog_next_time:
// ... or if there's no next timer yet
ld b32 $r10 D[$r0 + #time_next]
cmp b32 $r10 0
bra z #intr_watchdog_next_time_set
cmp b32 $r9 $r10
bra g #intr_watchdog_next_proc
intr_watchdog_next_time_set:
st b32 D[$r0 + #time_next] $r9
// update process' timer status, and advance
intr_watchdog_next_proc:
st b32 D[$r14 + #proc_time] $r9
add b32 $r14 #proc_size
cmp b32 $r14 #proc_list_tail
bra ne #intr_watchdog
ret
intr:
push $r0
clear b32 $r0
push $r8
push $r9
push $r10
push $r11
push $r12
push $r13
push $r14
push $r15
mov $r15 #proc_kern
mov $r8 $flags
push $r8
nv_iord($r8, NV_PPWR_DSCRATCH(0))
add b32 $r8 1
nv_iowr(NV_PPWR_DSCRATCH(0), $r8)
nv_iord($r8, NV_PPWR_INTR)
and $r9 $r8 NV_PPWR_INTR_WATCHDOG
bra z #intr_skip_watchdog
st b32 D[$r0 + #time_next] $r0
mov $r14 #proc_list_head
call(intr_watchdog)
ld b32 $r9 D[$r0 + #time_next]
cmp b32 $r9 0
bra z #intr_skip_watchdog
nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9)
st b32 D[$r0 + #time_prev] $r9
intr_skip_watchdog:
and $r9 $r8 NV_PPWR_INTR_SUBINTR
bra z #intr_skip_subintr
nv_iord($r9, NV_PPWR_SUBINTR)
and $r10 $r9 NV_PPWR_SUBINTR_FIFO
bra z #intr_subintr_skip_fifo
nv_iord($r12, NV_PPWR_FIFO_INTR)
push $r12
mov $r14 (PROC_HOST & 0x0000ffff)
sethi $r14 (PROC_HOST & 0xffff0000)
mov $r13 KMSG_FIFO
call(send)
pop $r12
nv_iowr(NV_PPWR_FIFO_INTR, $r12)
intr_subintr_skip_fifo:
nv_iowr(NV_PPWR_SUBINTR, $r9)
intr_skip_subintr:
and $r9 $r8 NV_PPWR_INTR_PAUSE
bra z #intr_skip_pause
and $r10 0xffbf
intr_skip_pause:
and $r9 $r8 NV_PPWR_INTR_USER0
bra z #intr_skip_user0
and $r10 0xffbf
intr_skip_user0:
nv_iowr(NV_PPWR_INTR_ACK, $r8)
pop $r8
mov $flags $r8
pop $r15
pop $r14
pop $r13
pop $r12
pop $r11
pop $r10
pop $r9
pop $r8
pop $r0
bclr $flags $p0
iret
// calculate the number of ticks in the specified nanoseconds delay
//
// $r15 - current
// $r14 - ns
// $r14 - ticks (return)
// $r0 - zero
ticks_from_ns:
push $r12
push $r11
/* try not losing precision (multiply then divide) */
imm32($r13, HW_TICKS_PER_US)
call #mulu32_32_64
/* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */
div $r12 $r12 1000
/* check if there wasn't any overflow */
cmpu b32 $r11 0
bra e #ticks_from_ns_quit
/* let's divide then multiply, too bad for the precision! */
div $r14 $r14 1000
imm32($r13, HW_TICKS_PER_US)
call #mulu32_32_64
/* this cannot overflow as long as HW_TICKS_PER_US < 1000 */
ticks_from_ns_quit:
mov b32 $r14 $r12
pop $r11
pop $r12
ret
// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - us
// $r14 - ticks (return)
// $r0 - zero
ticks_from_us:
push $r12
push $r11
/* simply multiply $us by HW_TICKS_PER_US */
imm32($r13, HW_TICKS_PER_US)
call #mulu32_32_64
mov b32 $r14 $r12
/* check if there wasn't any overflow */
cmpu b32 $r11 0
bra e #ticks_from_us_quit
/* Overflow! */
clear b32 $r14
ticks_from_us_quit:
pop $r11
pop $r12
ret
// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - ticks
// $r14 - us (return)
// $r0 - zero
ticks_to_us:
/* simply divide $ticks by HW_TICKS_PER_US */
imm32($r13, HW_TICKS_PER_US)
div $r14 $r14 $r13
ret
// request the current process be sent a message after a timeout expires
//
// $r15 - current
// $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow)
// $r0 - zero
timer:
push $r9
push $r8
// interrupts off to prevent racing with timer isr
bclr $flags ie0
// if current process already has a timer set, bail
ld b32 $r8 D[$r15 + #proc_time]
cmp b32 $r8 0
bra g #timer_done
// halt watchdog timer temporarily
clear b32 $r8
nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)
// find out how much time elapsed since the last update
// of the watchdog and add this time to the wanted ticks
nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
ld b32 $r9 D[$r0 + #time_prev]
sub b32 $r9 $r8
add b32 $r14 $r9
st b32 D[$r15 + #proc_time] $r14
// check for a pending interrupt. if there's one already
// pending, we can just bail since the timer isr will
// queue the next soonest right after it's done
nv_iord($r8, NV_PPWR_INTR)
and $r8 NV_PPWR_INTR_WATCHDOG
bra nz #timer_enable
// update the watchdog if this timer should expire first,
// or if there's no timeout already set
nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
cmp b32 $r14 $r0
bra e #timer_reset
cmp b32 $r14 $r8
bra g #timer_enable
timer_reset:
nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14)
st b32 D[$r0 + #time_prev] $r14
// re-enable the watchdog timer
timer_enable:
mov $r8 1
nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)
// interrupts back on
timer_done:
bset $flags ie0
pop $r8
pop $r9
ret
// send message to another process
//
// $r15 - current
// $r14 - process
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0 - zero
send_proc:
push $r8
push $r9
// check for space in queue
ld b32 $r8 D[$r14 + #proc_qget]
ld b32 $r9 D[$r14 + #proc_qput]
xor $r8 #proc_qmaskb
cmp b32 $r8 $r9
bra e #send_done
// enqueue message
and $r8 $r9 #proc_qmaskp
shl b32 $r8 $r8 #proc_qlen
add b32 $r8 #proc_queue
add b32 $r8 $r14
ld b32 $r10 D[$r15 + #proc_id]
st b32 D[$r8 + #msg_process] $r10
st b32 D[$r8 + #msg_message] $r13
st b32 D[$r8 + #msg_data0] $r12
st b32 D[$r8 + #msg_data1] $r11
// increment PUT
add b32 $r9 1
and $r9 #proc_qmaskf
st b32 D[$r14 + #proc_qput] $r9
bset $flags $p2
send_done:
pop $r9
pop $r8
ret
// lookup process structure by its name
//
// $r15 - current
// $r14 - process name
// $r0 - zero
//
// $r14 - process
// $p1 - success
find:
push $r8
mov $r8 #proc_list_head
bset $flags $p1
find_loop:
ld b32 $r10 D[$r8 + #proc_id]
cmp b32 $r10 $r14
bra e #find_done
add b32 $r8 #proc_size
cmp b32 $r8 #proc_list_tail
bra ne #find_loop
bclr $flags $p1
find_done:
mov b32 $r14 $r8
pop $r8
ret
// send message to another process
//
// $r15 - current
// $r14 - process id
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0 - zero
send:
call(find)
bra $p1 #send_proc
ret
// process single message for a given process
//
// $r15 - current
// $r14 - process
// $r0 - zero
recv:
push $r9
push $r8
ld b32 $r8 D[$r14 + #proc_qget]
ld b32 $r9 D[$r14 + #proc_qput]
bclr $flags $p1
cmp b32 $r8 $r9
bra e #recv_done
// dequeue message
and $r9 $r8 #proc_qmaskp
add b32 $r8 1
and $r8 #proc_qmaskf
st b32 D[$r14 + #proc_qget] $r8
ld b32 $r10 D[$r14 + #proc_recv]
push $r15
mov $r15 $flags
push $r15
mov b32 $r15 $r14
shl b32 $r9 $r9 #proc_qlen
add b32 $r14 $r9
add b32 $r14 #proc_queue
ld b32 $r11 D[$r14 + #msg_data1]
ld b32 $r12 D[$r14 + #msg_data0]
ld b32 $r13 D[$r14 + #msg_message]
ld b32 $r14 D[$r14 + #msg_process]
// process it
call $r10
pop $r15
mov $flags $r15
bset $flags $p1
pop $r15
recv_done:
pop $r8
pop $r9
ret
init:
// setup stack
nv_iord($r1, NV_PPWR_CAPS)
extr $r1 $r1 9:17
shl b32 $r1 8
mov $sp $r1
#ifdef NVKM_FALCON_MMIO_UAS
// somehow allows the magic "access mmio via D[]" stuff that's
// used by the nv_rd32/nv_wr32 macros to work
mov $r1 0x0010
sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE
nv_iowrs(NV_PPWR_UAS_CONFIG, $r1)
#endif
// route all interrupts except user0/1 and pause to fuc
mov $r1 0x00e0
sethi $r1 0x00000000
nv_iowr(NV_PPWR_INTR_ROUTE, $r1)
// enable watchdog and subintr intrs
mov $r1 NV_PPWR_INTR_EN_CLR_MASK
nv_iowr(NV_PPWR_INTR_EN_CLR, $r1)
mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG
or $r1 NV_PPWR_INTR_EN_SET_SUBINTR
nv_iowr(NV_PPWR_INTR_EN_SET, $r1)
// enable interrupts globally
mov $r1 #intr
sethi $r1 0x00000000
mov $iv0 $r1
bset $flags ie0
// enable watchdog timer
mov $r1 1
nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1)
// bootstrap processes, idle process will be last, and not return
mov $r15 #proc_list_head
init_proc:
ld b32 $r1 D[$r15 + #proc_init]
cmp b32 $r1 0
bra z #init_proc
call $r1
add b32 $r15 #proc_size
bra #init_proc
#endif

View file

@ -0,0 +1,272 @@
/*
* Copyright 2013 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
*/
#define GT215 0xa3
#define GF100 0xc0
#define GF119 0xd9
#define GK208 0x108
#include "os.h"
// IO addresses
#define NV_PPWR_INTR_TRIGGER 0x0000
#define NV_PPWR_INTR_TRIGGER_USER1 0x00000080
#define NV_PPWR_INTR_TRIGGER_USER0 0x00000040
#define NV_PPWR_INTR_ACK 0x0004
#define NV_PPWR_INTR_ACK_SUBINTR 0x00000800
#define NV_PPWR_INTR_ACK_WATCHDOG 0x00000002
#define NV_PPWR_INTR 0x0008
#define NV_PPWR_INTR_SUBINTR 0x00000800
#define NV_PPWR_INTR_USER1 0x00000080
#define NV_PPWR_INTR_USER0 0x00000040
#define NV_PPWR_INTR_PAUSE 0x00000020
#define NV_PPWR_INTR_WATCHDOG 0x00000002
#define NV_PPWR_INTR_EN_SET 0x0010
#define NV_PPWR_INTR_EN_SET_SUBINTR 0x00000800
#define NV_PPWR_INTR_EN_SET_WATCHDOG 0x00000002
#define NV_PPWR_INTR_EN_CLR 0x0014
#define NV_PPWR_INTR_EN_CLR_MASK /* fuck i hate envyas */ -1
#define NV_PPWR_INTR_ROUTE 0x001c
#define NV_PPWR_TIMER_LOW 0x002c
#define NV_PPWR_WATCHDOG_TIME 0x0034
#define NV_PPWR_WATCHDOG_ENABLE 0x0038
#define NV_PPWR_CAPS 0x0108
#define NV_PPWR_UAS_CONFIG 0x0164
#define NV_PPWR_UAS_CONFIG_ENABLE 0x00010000
#if NVKM_PPWR_CHIPSET >= GK208
#define NV_PPWR_DSCRATCH(i) (4 * (i) + 0x0450)
#endif
#define NV_PPWR_FIFO_PUT(i) (4 * (i) + 0x04a0)
#define NV_PPWR_FIFO_GET(i) (4 * (i) + 0x04b0)
#define NV_PPWR_FIFO_INTR 0x04c0
#define NV_PPWR_FIFO_INTR_EN 0x04c4
#define NV_PPWR_RFIFO_PUT 0x04c8
#define NV_PPWR_RFIFO_GET 0x04cc
#define NV_PPWR_H2D 0x04d0
#define NV_PPWR_D2H 0x04dc
#if NVKM_PPWR_CHIPSET < GK208
#define NV_PPWR_DSCRATCH(i) (4 * (i) + 0x05d0)
#endif
#define NV_PPWR_SUBINTR 0x0688
#define NV_PPWR_SUBINTR_FIFO 0x00000002
#define NV_PPWR_MMIO_ADDR 0x07a0
#define NV_PPWR_MMIO_DATA 0x07a4
#define NV_PPWR_MMIO_CTRL 0x07ac
#define NV_PPWR_MMIO_CTRL_TRIGGER 0x00010000
#define NV_PPWR_MMIO_CTRL_STATUS 0x00007000
#define NV_PPWR_MMIO_CTRL_STATUS_IDLE 0x00000000
#define NV_PPWR_MMIO_CTRL_MASK 0x000000f0
#define NV_PPWR_MMIO_CTRL_MASK_B32_0 0x000000f0
#define NV_PPWR_MMIO_CTRL_OP 0x00000003
#define NV_PPWR_MMIO_CTRL_OP_RD 0x00000001
#define NV_PPWR_MMIO_CTRL_OP_WR 0x00000002
#define NV_PPWR_OUTPUT 0x07c0
#define NV_PPWR_OUTPUT_FB_PAUSE 0x00000004
#if NVKM_PPWR_CHIPSET < GF119
#define NV_PPWR_OUTPUT_I2C_3_SCL 0x00000100
#define NV_PPWR_OUTPUT_I2C_3_SDA 0x00000200
#define NV_PPWR_OUTPUT_I2C_0_SCL 0x00001000
#define NV_PPWR_OUTPUT_I2C_0_SDA 0x00002000
#define NV_PPWR_OUTPUT_I2C_1_SCL 0x00004000
#define NV_PPWR_OUTPUT_I2C_1_SDA 0x00008000
#define NV_PPWR_OUTPUT_I2C_2_SCL 0x00010000
#define NV_PPWR_OUTPUT_I2C_2_SDA 0x00020000
#define NV_PPWR_OUTPUT_I2C_4_SCL 0x00040000
#define NV_PPWR_OUTPUT_I2C_4_SDA 0x00080000
#define NV_PPWR_OUTPUT_I2C_5_SCL 0x00100000
#define NV_PPWR_OUTPUT_I2C_5_SDA 0x00200000
#define NV_PPWR_OUTPUT_I2C_6_SCL 0x00400000
#define NV_PPWR_OUTPUT_I2C_6_SDA 0x00800000
#define NV_PPWR_OUTPUT_I2C_7_SCL 0x01000000
#define NV_PPWR_OUTPUT_I2C_7_SDA 0x02000000
#define NV_PPWR_OUTPUT_I2C_8_SCL 0x04000000
#define NV_PPWR_OUTPUT_I2C_8_SDA 0x08000000
#define NV_PPWR_OUTPUT_I2C_9_SCL 0x10000000
#define NV_PPWR_OUTPUT_I2C_9_SDA 0x20000000
#else
#define NV_PPWR_OUTPUT_I2C_0_SCL 0x00000400
#define NV_PPWR_OUTPUT_I2C_1_SCL 0x00000800
#define NV_PPWR_OUTPUT_I2C_2_SCL 0x00001000
#define NV_PPWR_OUTPUT_I2C_3_SCL 0x00002000
#define NV_PPWR_OUTPUT_I2C_4_SCL 0x00004000
#define NV_PPWR_OUTPUT_I2C_5_SCL 0x00008000
#define NV_PPWR_OUTPUT_I2C_6_SCL 0x00010000
#define NV_PPWR_OUTPUT_I2C_7_SCL 0x00020000
#define NV_PPWR_OUTPUT_I2C_8_SCL 0x00040000
#define NV_PPWR_OUTPUT_I2C_9_SCL 0x00080000
#define NV_PPWR_OUTPUT_I2C_0_SDA 0x00100000
#define NV_PPWR_OUTPUT_I2C_1_SDA 0x00200000
#define NV_PPWR_OUTPUT_I2C_2_SDA 0x00400000
#define NV_PPWR_OUTPUT_I2C_3_SDA 0x00800000
#define NV_PPWR_OUTPUT_I2C_4_SDA 0x01000000
#define NV_PPWR_OUTPUT_I2C_5_SDA 0x02000000
#define NV_PPWR_OUTPUT_I2C_6_SDA 0x04000000
#define NV_PPWR_OUTPUT_I2C_7_SDA 0x08000000
#define NV_PPWR_OUTPUT_I2C_8_SDA 0x10000000
#define NV_PPWR_OUTPUT_I2C_9_SDA 0x20000000
#endif
#define NV_PPWR_INPUT 0x07c4
#define NV_PPWR_OUTPUT_SET 0x07e0
#define NV_PPWR_OUTPUT_SET_FB_PAUSE 0x00000004
#define NV_PPWR_OUTPUT_CLR 0x07e4
#define NV_PPWR_OUTPUT_CLR_FB_PAUSE 0x00000004
// Inter-process message format
.equ #msg_process 0x00 /* send() target, recv() sender */
.equ #msg_message 0x04
.equ #msg_data0 0x08
.equ #msg_data1 0x0c
// Kernel message IDs
#define KMSG_FIFO 0x00000000
#define KMSG_ALARM 0x00000001
// Process message queue description
.equ #proc_qlen 4 // log2(size of queue entry in bytes)
.equ #proc_qnum 2 // log2(max number of entries in queue)
.equ #proc_qmaskb (1 << #proc_qnum) // max number of entries in queue
.equ #proc_qmaskp (#proc_qmaskb - 1)
.equ #proc_qmaskf ((#proc_qmaskb << 1) - 1)
.equ #proc_qsize (1 << (#proc_qlen + #proc_qnum))
// Process table entry
.equ #proc_id 0x00
.equ #proc_init 0x04
.equ #proc_recv 0x08
.equ #proc_time 0x0c
.equ #proc_qput 0x10
.equ #proc_qget 0x14
.equ #proc_queue 0x18
.equ #proc_size (0x18 + #proc_qsize)
#define process(id,init,recv) /*
*/ .b32 id /*
*/ .b32 init /*
*/ .b32 recv /*
*/ .b32 0 /*
*/ .b32 0 /*
*/ .b32 0 /*
*/ .skip 64
#if NV_PPWR_CHIPSET < GK208
#define imm32(reg,val) /*
*/ movw reg ((val) & 0x0000ffff) /*
*/ sethi reg ((val) & 0xffff0000)
#else
#define imm32(reg,val) /*
*/ mov reg (val)
#endif
#ifndef NVKM_FALCON_UNSHIFTED_IO
#define nv_iord(reg,ior) /*
*/ mov reg ior /*
*/ shl b32 reg 6 /*
*/ iord reg I[reg + 0x000]
#else
#define nv_iord(reg,ior) /*
*/ mov reg ior /*
*/ iord reg I[reg + 0x000]
#endif
#ifndef NVKM_FALCON_UNSHIFTED_IO
#define nv_iowr(ior,reg) /*
*/ mov $r0 ior /*
*/ shl b32 $r0 6 /*
*/ iowr I[$r0 + 0x000] reg /*
*/ clear b32 $r0
#else
#define nv_iowr(ior,reg) /*
*/ mov $r0 ior /*
*/ iowr I[$r0 + 0x000] reg /*
*/ clear b32 $r0
#endif
#ifndef NVKM_FALCON_UNSHIFTED_IO
#define nv_iowrs(ior,reg) /*
*/ mov $r0 ior /*
*/ shl b32 $r0 6 /*
*/ iowrs I[$r0 + 0x000] reg /*
*/ clear b32 $r0
#else
#define nv_iowrs(ior,reg) /*
*/ mov $r0 ior /*
*/ iowrs I[$r0 + 0x000] reg /*
*/ clear b32 $r0
#endif
#define hash #
#define fn(a) a
#ifndef NVKM_FALCON_PC24
#define call(a) call fn(hash)a
#else
#define call(a) lcall fn(hash)a
#endif
#ifndef NVKM_FALCON_MMIO_UAS
#define nv_rd32(reg,addr) /*
*/ mov b32 $r14 addr /*
*/ call(rd32) /*
*/ mov b32 reg $r13
#else
#define nv_rd32(reg,addr) /*
*/ sethi $r0 0x14000000 /*
*/ or $r0 addr /*
*/ ld b32 reg D[$r0] /*
*/ clear b32 $r0
#endif
#if !defined(NVKM_FALCON_MMIO_UAS) || defined(NVKM_FALCON_MMIO_TRAP)
#define nv_wr32(addr,reg) /*
*/ push addr /*
*/ push reg /*
*/ pop $r13 /*
*/ pop $r14 /*
*/ call(wr32)
#else
#define nv_wr32(addr,reg) /*
*/ sethi $r0 0x14000000 /*
*/ or $r0 addr /*
*/ st b32 D[$r0] reg /*
*/ clear b32 $r0
#endif
#define st(size, addr, reg) /*
*/ movw $r0 addr /*
*/ st size D[$r0] reg /*
*/ clear b32 $r0
#define ld(size, reg, addr) /*
*/ movw $r0 addr /*
*/ ld size reg D[$r0] /*
*/ clear b32 $r0
// does a 64+64 -> 64 unsigned addition (C = A + B)
#define addu64(reg_a_c_hi, reg_a_c_lo, b_hi, b_lo) /*
*/ add b32 reg_a_c_lo b_lo /*
*/ adc b32 reg_a_c_hi b_hi
// does a 64+64 -> 64 substraction (C = A - B)
#define subu64(reg_a_c_hi, reg_a_c_lo, b_hi, b_lo) /*
*/ sub b32 reg_a_c_lo b_lo /*
*/ sbb b32 reg_a_c_hi b_hi

Some files were not shown because too many files have changed in this diff Show more