From 3ca6cd435effd1d762217529baaab010f34f8cc8 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Tue, 26 Aug 2014 00:26:38 +0200 Subject: [PATCH] drm/nouveau/subdev: add a pfuse subdev v2 We will use this subdev to disable temperature reading on cards that did not get a sensor calibration in the factory. v2: - rename "nouveau_fuse_rd32" to "gxXXX_fuse_rd32" as adviced by Christian Costa - fold the code a little as adviced by Emil Velikov Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 4 + .../drm/nouveau/core/engine/device/gm100.c | 2 + .../gpu/drm/nouveau/core/engine/device/nv50.c | 15 ++++ .../gpu/drm/nouveau/core/engine/device/nvc0.c | 10 +++ .../gpu/drm/nouveau/core/engine/device/nve0.c | 8 ++ .../drm/nouveau/core/include/core/device.h | 1 + .../drm/nouveau/core/include/subdev/fuse.h | 30 +++++++ .../gpu/drm/nouveau/core/subdev/fuse/base.c | 54 ++++++++++++ .../gpu/drm/nouveau/core/subdev/fuse/g80.c | 81 ++++++++++++++++++ .../gpu/drm/nouveau/core/subdev/fuse/gf100.c | 83 +++++++++++++++++++ .../gpu/drm/nouveau/core/subdev/fuse/gm107.c | 66 +++++++++++++++ .../gpu/drm/nouveau/core/subdev/fuse/priv.h | 9 ++ 12 files changed, 363 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/include/subdev/fuse.h create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fuse/base.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fuse/g80.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fuse/gf100.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fuse/gm107.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fuse/priv.h diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index c6631812d910..37ab09bea884 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -127,6 +127,10 @@ nouveau-y += core/subdev/fb/ramgk20a.o nouveau-y += core/subdev/fb/ramgm107.o nouveau-y += core/subdev/fb/sddr3.o nouveau-y += core/subdev/fb/gddr5.o +nouveau-y += core/subdev/fuse/base.o +nouveau-y += core/subdev/fuse/g80.o +nouveau-y += core/subdev/fuse/gf100.o +nouveau-y += core/subdev/fuse/gm107.o nouveau-y += core/subdev/gpio/base.o nouveau-y += core/subdev/gpio/nv10.o nouveau-y += core/subdev/gpio/nv50.o diff --git a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c index 9e9f5670faa2..6295668e29a5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ gm100_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gm107_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &gm107_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c index 932f84fae459..ca265fe30927 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -87,6 +89,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -115,6 +118,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -143,6 +147,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -171,6 +176,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -199,6 +205,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -227,6 +234,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -255,6 +263,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -283,6 +292,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -311,6 +321,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -339,6 +350,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -369,6 +381,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -398,6 +411,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -427,6 +441,7 @@ nv50_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &g80_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c index b4a2917ce555..89b9fd411ef0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -94,6 +96,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -126,6 +129,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -157,6 +161,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -189,6 +194,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -221,6 +227,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -252,6 +259,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -284,6 +292,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -315,6 +324,7 @@ nvc0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nvd0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = gf117_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index cdf9147f32a1..b1b2e484ecfa 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -95,6 +97,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -128,6 +131,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -161,6 +165,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_CLOCK ] = &gk20a_clock_oclass; device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass; device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; @@ -180,6 +185,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -213,6 +219,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; @@ -246,6 +253,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 8743766454a5..1d9d893929bb 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -24,6 +24,7 @@ enum nv_subdev_type { * been created, and are allowed to assume any subdevs in the * list above them exist and have been initialised. */ + NVDEV_SUBDEV_FUSE, NVDEV_SUBDEV_MXM, NVDEV_SUBDEV_MC, NVDEV_SUBDEV_BUS, diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fuse.h b/drivers/gpu/drm/nouveau/core/include/subdev/fuse.h new file mode 100644 index 000000000000..2b1ddb2a9a7d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fuse.h @@ -0,0 +1,30 @@ +#ifndef __NOUVEAU_FUSE_H__ +#define __NOUVEAU_FUSE_H__ + +#include +#include + +struct nouveau_fuse { + struct nouveau_subdev base; +}; + +static inline struct nouveau_fuse * +nouveau_fuse(void *obj) +{ + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FUSE]; +} + +#define nouveau_fuse_create(p, e, o, d) \ + nouveau_fuse_create_((p), (e), (o), sizeof(**d), (void **)d) + +int nouveau_fuse_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +void _nouveau_fuse_dtor(struct nouveau_object *); +int _nouveau_fuse_init(struct nouveau_object *); +#define _nouveau_fuse_fini _nouveau_subdev_fini + +extern struct nouveau_oclass g80_fuse_oclass; +extern struct nouveau_oclass gf100_fuse_oclass; +extern struct nouveau_oclass gm107_fuse_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fuse/base.c b/drivers/gpu/drm/nouveau/core/subdev/fuse/base.c new file mode 100644 index 000000000000..9e8e92127715 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fuse/base.c @@ -0,0 +1,54 @@ +/* + * Copyright 2014 Martin Peres + * + * 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: Martin Peres + */ + +#include + +int +_nouveau_fuse_init(struct nouveau_object *object) +{ + struct nouveau_fuse *fuse = (void *)object; + return nouveau_subdev_init(&fuse->base); +} + +void +_nouveau_fuse_dtor(struct nouveau_object *object) +{ + struct nouveau_fuse *fuse = (void *)object; + nouveau_subdev_destroy(&fuse->base); +} + +int +nouveau_fuse_create_(struct nouveau_object *parent, + struct nouveau_object *engine, + struct nouveau_oclass *oclass, int length, void **pobject) +{ + struct nouveau_fuse *fuse; + int ret; + + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "FUSE", + "fuse", length, pobject); + fuse = *pobject; + + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fuse/g80.c b/drivers/gpu/drm/nouveau/core/subdev/fuse/g80.c new file mode 100644 index 000000000000..a374ade485be --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fuse/g80.c @@ -0,0 +1,81 @@ +/* + * Copyright 2014 Martin Peres + * + * 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: Martin Peres + */ + +#include "priv.h" + +struct g80_fuse_priv { + struct nouveau_fuse base; + + spinlock_t fuse_enable_lock; +}; + +static u32 +g80_fuse_rd32(struct nouveau_object *object, u64 addr) +{ + struct g80_fuse_priv *priv = (void *)object; + unsigned long flags; + u32 fuse_enable, val; + + spin_lock_irqsave(&priv->fuse_enable_lock, flags); + + /* racy if another part of nouveau start writing to this reg */ + fuse_enable = nv_mask(priv, 0x1084, 0x800, 0x800); + val = nv_rd32(priv, 0x21000 + addr); + nv_wr32(priv, 0x1084, fuse_enable); + + spin_unlock_irqrestore(&priv->fuse_enable_lock, flags); + + return val; +} + + +static int +g80_fuse_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct g80_fuse_priv *priv; + int ret; + + ret = nouveau_fuse_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + spin_lock_init(&priv->fuse_enable_lock); + + return 0; +} + +struct nouveau_oclass +g80_fuse_oclass = { + .handle = NV_SUBDEV(FUSE, 0x50), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = g80_fuse_ctor, + .dtor = _nouveau_fuse_dtor, + .init = _nouveau_fuse_init, + .fini = _nouveau_fuse_fini, + .rd32 = g80_fuse_rd32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fuse/gf100.c b/drivers/gpu/drm/nouveau/core/subdev/fuse/gf100.c new file mode 100644 index 000000000000..5ed03f54b3d4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fuse/gf100.c @@ -0,0 +1,83 @@ +/* + * Copyright 2014 Martin Peres + * + * 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: Martin Peres + */ + +#include "priv.h" + +struct gf100_fuse_priv { + struct nouveau_fuse base; + + spinlock_t fuse_enable_lock; +}; + +static u32 +gf100_fuse_rd32(struct nouveau_object *object, u64 addr) +{ + struct gf100_fuse_priv *priv = (void *)object; + unsigned long flags; + u32 fuse_enable, unk, val; + + spin_lock_irqsave(&priv->fuse_enable_lock, flags); + + /* racy if another part of nouveau start writing to these regs */ + fuse_enable = nv_mask(priv, 0x22400, 0x800, 0x800); + unk = nv_mask(priv, 0x21000, 0x1, 0x1); + val = nv_rd32(priv, 0x21100 + addr); + nv_wr32(priv, 0x21000, unk); + nv_wr32(priv, 0x22400, fuse_enable); + + spin_unlock_irqrestore(&priv->fuse_enable_lock, flags); + + return val; +} + + +static int +gf100_fuse_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct gf100_fuse_priv *priv; + int ret; + + ret = nouveau_fuse_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + spin_lock_init(&priv->fuse_enable_lock); + + return 0; +} + +struct nouveau_oclass +gf100_fuse_oclass = { + .handle = NV_SUBDEV(FUSE, 0xC0), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = gf100_fuse_ctor, + .dtor = _nouveau_fuse_dtor, + .init = _nouveau_fuse_init, + .fini = _nouveau_fuse_fini, + .rd32 = gf100_fuse_rd32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fuse/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/fuse/gm107.c new file mode 100644 index 000000000000..4f1a636c6538 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fuse/gm107.c @@ -0,0 +1,66 @@ +/* + * Copyright 2014 Martin Peres + * + * 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: Martin Peres + */ + +#include "priv.h" + +struct gm107_fuse_priv { + struct nouveau_fuse base; +}; + +static u32 +gm107_fuse_rd32(struct nouveau_object *object, u64 addr) +{ + struct gf100_fuse_priv *priv = (void *)object; + + return nv_rd32(priv, 0x21100 + addr); +} + + +static int +gm107_fuse_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct gm107_fuse_priv *priv; + int ret; + + ret = nouveau_fuse_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + return 0; +} + +struct nouveau_oclass +gm107_fuse_oclass = { + .handle = NV_SUBDEV(FUSE, 0x117), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = gm107_fuse_ctor, + .dtor = _nouveau_fuse_dtor, + .init = _nouveau_fuse_init, + .fini = _nouveau_fuse_fini, + .rd32 = gm107_fuse_rd32, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fuse/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fuse/priv.h new file mode 100644 index 000000000000..d2085411a5cb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fuse/priv.h @@ -0,0 +1,9 @@ +#ifndef __NVKM_FUSE_PRIV_H__ +#define __NVKM_FUSE_PRIV_H__ + +#include + +int _nouveau_fuse_init(struct nouveau_object *object); +void _nouveau_fuse_dtor(struct nouveau_object *object); + +#endif -- 2.39.5