aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2016-05-30 08:23:41 +1000
committerBen Skeggs <bskeggs@redhat.com>2016-07-14 11:53:25 +1000
commit3c2a536b0cbac98035cba42c880c58fd399cb167 (patch)
tree2205bb8a12fb2d245f8da2dbb53feb40ae0fb263 /drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
parentdrm/nouveau/mc: take nvkm_device as argument to public functions (diff)
downloadlinux-dev-3c2a536b0cbac98035cba42c880c58fd399cb167.tar.xz
linux-dev-3c2a536b0cbac98035cba42c880c58fd399cb167.zip
drm/nouveau/mc: expose device enable/disable separately, as well as reset
There are cases where subdevs need to perform additonal actions around the master reset, so we want to expost the operations separately. This commit also adds a flag to the NV_PMC_ENABLE bitfield definitions which allow skipping the automatic reset() called from core/subdev.c. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
index 563a528d42ce..e887df08e8cf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
@@ -95,22 +95,32 @@ nvkm_mc_intr(struct nvkm_device *device, bool *handled)
*handled = intr != 0;
}
-static void
-nvkm_mc_reset_(struct nvkm_mc *mc, enum nvkm_devidx devidx)
+static u32
+nvkm_mc_reset_mask(struct nvkm_device *device, bool isauto,
+ enum nvkm_devidx devidx)
{
- struct nvkm_device *device = mc->subdev.device;
+ struct nvkm_mc *mc = device->mc;
const struct nvkm_mc_map *map;
- u64 pmc_enable;
-
- if (!(pmc_enable = nvkm_top_reset(device, devidx))) {
- for (map = mc->func->reset; map && map->stat; map++) {
- if (map->unit == devidx) {
- pmc_enable = map->stat;
- break;
+ u64 pmc_enable = 0;
+ if (likely(mc)) {
+ if (!(pmc_enable = nvkm_top_reset(device, devidx))) {
+ for (map = mc->func->reset; map && map->stat; map++) {
+ if (!isauto || !map->noauto) {
+ if (map->unit == devidx) {
+ pmc_enable = map->stat;
+ break;
+ }
+ }
}
}
}
+ return pmc_enable;
+}
+void
+nvkm_mc_reset(struct nvkm_device *device, enum nvkm_devidx devidx)
+{
+ u64 pmc_enable = nvkm_mc_reset_mask(device, true, devidx);
if (pmc_enable) {
nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
@@ -119,11 +129,21 @@ nvkm_mc_reset_(struct nvkm_mc *mc, enum nvkm_devidx devidx)
}
void
-nvkm_mc_reset(struct nvkm_device *device, enum nvkm_devidx devidx)
+nvkm_mc_disable(struct nvkm_device *device, enum nvkm_devidx devidx)
{
- struct nvkm_mc *mc = device->mc;
- if (likely(mc))
- nvkm_mc_reset_(mc, devidx);
+ u64 pmc_enable = nvkm_mc_reset_mask(device, false, devidx);
+ if (pmc_enable)
+ nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
+}
+
+void
+nvkm_mc_enable(struct nvkm_device *device, enum nvkm_devidx devidx)
+{
+ u64 pmc_enable = nvkm_mc_reset_mask(device, false, devidx);
+ if (pmc_enable) {
+ nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
+ nvkm_rd32(device, 0x000200);
+ }
}
static int