Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: MIT
nvkm-y += nvkm/subdev/bar/base.o
nvkm-y += nvkm/subdev/bar/nv50.o
nvkm-y += nvkm/subdev/bar/g84.o
nvkm-y += nvkm/subdev/bar/gf100.o
nvkm-y += nvkm/subdev/bar/gk20a.o
nvkm-y += nvkm/subdev/bar/gm107.o
nvkm-y += nvkm/subdev/bar/gm20b.o
nvkm-y += nvkm/subdev/bar/tu102.o
@@ -0,0 +1,150 @@
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "priv.h"
void
nvkm_bar_flush(struct nvkm_bar *bar)
{
if (bar && bar->func->flush)
bar->func->flush(bar);
}
struct nvkm_vmm *
nvkm_bar_bar1_vmm(struct nvkm_device *device)
{
return device->bar->func->bar1.vmm(device->bar);
}
void
nvkm_bar_bar1_reset(struct nvkm_device *device)
{
struct nvkm_bar *bar = device->bar;
if (bar) {
bar->func->bar1.init(bar);
bar->func->bar1.wait(bar);
}
}
struct nvkm_vmm *
nvkm_bar_bar2_vmm(struct nvkm_device *device)
{
/* Denies access to BAR2 when it's not initialised, used by INSTMEM
* to know when object access needs to go through the BAR0 window.
*/
struct nvkm_bar *bar = device->bar;
if (bar && bar->bar2)
return bar->func->bar2.vmm(bar);
return NULL;
}
void
nvkm_bar_bar2_reset(struct nvkm_device *device)
{
struct nvkm_bar *bar = device->bar;
if (bar && bar->bar2) {
bar->func->bar2.init(bar);
bar->func->bar2.wait(bar);
}
}
void
nvkm_bar_bar2_fini(struct nvkm_device *device)
{
struct nvkm_bar *bar = device->bar;
if (bar && bar->bar2) {
bar->func->bar2.fini(bar);
bar->bar2 = false;
}
}
void
nvkm_bar_bar2_init(struct nvkm_device *device)
{
struct nvkm_bar *bar = device->bar;
if (bar && bar->subdev.oneinit && !bar->bar2 && bar->func->bar2.init) {
bar->func->bar2.init(bar);
bar->func->bar2.wait(bar);
bar->bar2 = true;
}
}
static int
nvkm_bar_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
struct nvkm_bar *bar = nvkm_bar(subdev);
if (!subdev->use.enabled)
return 0;
if (bar->func->bar1.fini)
bar->func->bar1.fini(bar);
if (!suspend) /* Handled by instmem. */
nvkm_bar_bar2_fini(subdev->device);
return 0;
}
static int
nvkm_bar_init(struct nvkm_subdev *subdev)
{
struct nvkm_bar *bar = nvkm_bar(subdev);
bar->func->bar1.init(bar);
bar->func->bar1.wait(bar);
if (bar->func->init)
bar->func->init(bar);
return 0;
}
static int
nvkm_bar_oneinit(struct nvkm_subdev *subdev)
{
struct nvkm_bar *bar = nvkm_bar(subdev);
return bar->func->oneinit(bar);
}
static void *
nvkm_bar_dtor(struct nvkm_subdev *subdev)
{
struct nvkm_bar *bar = nvkm_bar(subdev);
return bar->func->dtor(bar);
}
static const struct nvkm_subdev_func
nvkm_bar = {
.dtor = nvkm_bar_dtor,
.oneinit = nvkm_bar_oneinit,
.init = nvkm_bar_init,
.fini = nvkm_bar_fini,
};
void
nvkm_bar_ctor(const struct nvkm_bar_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_bar *bar)
{
nvkm_subdev_ctor(&nvkm_bar, device, type, inst, &bar->subdev);
bar->func = func;
spin_lock_init(&bar->lock);
}
@@ -0,0 +1,63 @@
/*
* Copyright 2015 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 <bskeggs@redhat.com>
*/
#include "nv50.h"
#include <subdev/timer.h>
void
g84_bar_flush(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
unsigned long flags;
spin_lock_irqsave(&bar->lock, flags);
nvkm_wr32(device, 0x070000, 0x00000001);
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x070000) & 0x00000002))
break;
);
spin_unlock_irqrestore(&bar->lock, flags);
}
static const struct nvkm_bar_func
g84_bar_func = {
.dtor = nv50_bar_dtor,
.oneinit = nv50_bar_oneinit,
.init = nv50_bar_init,
.bar1.init = nv50_bar_bar1_init,
.bar1.fini = nv50_bar_bar1_fini,
.bar1.wait = nv50_bar_bar1_wait,
.bar1.vmm = nv50_bar_bar1_vmm,
.bar2.init = nv50_bar_bar2_init,
.bar2.fini = nv50_bar_bar2_fini,
.bar2.wait = nv50_bar_bar1_wait,
.bar2.vmm = nv50_bar_bar2_vmm,
.flush = g84_bar_flush,
};
int
g84_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
return nv50_bar_new_(&g84_bar_func, device, type, inst, 0x200, pbar);
}
@@ -0,0 +1,196 @@
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "gf100.h"
#include <core/memory.h>
#include <core/option.h>
#include <subdev/fb.h>
#include <subdev/mmu.h>
struct nvkm_vmm *
gf100_bar_bar1_vmm(struct nvkm_bar *base)
{
return gf100_bar(base)->bar[1].vmm;
}
void
gf100_bar_bar1_wait(struct nvkm_bar *base)
{
/* NFI why it's twice. */
nvkm_bar_flush(base);
nvkm_bar_flush(base);
}
void
gf100_bar_bar1_fini(struct nvkm_bar *bar)
{
nvkm_mask(bar->subdev.device, 0x001704, 0x80000000, 0x00000000);
}
void
gf100_bar_bar1_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct gf100_bar *bar = gf100_bar(base);
const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
nvkm_wr32(device, 0x001704, 0x80000000 | addr);
}
struct nvkm_vmm *
gf100_bar_bar2_vmm(struct nvkm_bar *base)
{
return gf100_bar(base)->bar[0].vmm;
}
void
gf100_bar_bar2_fini(struct nvkm_bar *bar)
{
nvkm_mask(bar->subdev.device, 0x001714, 0x80000000, 0x00000000);
}
void
gf100_bar_bar2_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct gf100_bar *bar = gf100_bar(base);
u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
if (bar->bar2_halve)
addr |= 0x40000000;
nvkm_wr32(device, 0x001714, 0x80000000 | addr);
}
static int
gf100_bar_oneinit_bar(struct gf100_bar *bar, struct gf100_barN *bar_vm,
struct lock_class_key *key, enum nvkm_bar_id bar_id)
{
struct nvkm_device *device = bar->base.subdev.device;
resource_size_t bar_len;
int ret;
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false,
&bar_vm->inst);
if (ret)
return ret;
bar_len = device->func->resource_size(device, bar_id);
if (!bar_len)
return -ENOMEM;
if (bar_id == NVKM_BAR2_INST && bar->bar2_halve)
bar_len >>= 1;
ret = nvkm_vmm_new(device, 0, bar_len, NULL, 0, key,
(bar_id == NVKM_BAR2_INST) ? "bar2" : "bar1", &bar_vm->vmm);
if (ret)
return ret;
atomic_inc(&bar_vm->vmm->engref[NVKM_SUBDEV_BAR]);
bar_vm->vmm->debug = bar->base.subdev.debug;
/*
* Bootstrap page table lookup.
*/
if (bar_id == NVKM_BAR2_INST) {
ret = nvkm_vmm_boot(bar_vm->vmm);
if (ret)
return ret;
}
return nvkm_vmm_join(bar_vm->vmm, bar_vm->inst);
}
int
gf100_bar_oneinit(struct nvkm_bar *base)
{
static struct lock_class_key bar1_lock;
static struct lock_class_key bar2_lock;
struct gf100_bar *bar = gf100_bar(base);
int ret;
/* BAR2 */
if (bar->base.func->bar2.init) {
ret = gf100_bar_oneinit_bar(bar, &bar->bar[0], &bar2_lock, NVKM_BAR2_INST);
if (ret)
return ret;
bar->base.subdev.oneinit = true;
nvkm_bar_bar2_init(bar->base.subdev.device);
}
/* BAR1 */
ret = gf100_bar_oneinit_bar(bar, &bar->bar[1], &bar1_lock, NVKM_BAR1_FB);
if (ret)
return ret;
return 0;
}
void *
gf100_bar_dtor(struct nvkm_bar *base)
{
struct gf100_bar *bar = gf100_bar(base);
nvkm_vmm_part(bar->bar[1].vmm, bar->bar[1].inst);
nvkm_vmm_unref(&bar->bar[1].vmm);
nvkm_memory_unref(&bar->bar[1].inst);
nvkm_vmm_part(bar->bar[0].vmm, bar->bar[0].inst);
nvkm_vmm_unref(&bar->bar[0].vmm);
nvkm_memory_unref(&bar->bar[0].inst);
return bar;
}
int
gf100_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_bar **pbar)
{
struct gf100_bar *bar;
if (!(bar = kzalloc_obj(*bar)))
return -ENOMEM;
nvkm_bar_ctor(func, device, type, inst, &bar->base);
bar->bar2_halve = nvkm_boolopt(device->cfgopt, "NvBar2Halve", false);
*pbar = &bar->base;
return 0;
}
static const struct nvkm_bar_func
gf100_bar_func = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = gf100_bar_bar1_init,
.bar1.fini = gf100_bar_bar1_fini,
.bar1.wait = gf100_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.bar2.init = gf100_bar_bar2_init,
.bar2.fini = gf100_bar_bar2_fini,
.bar2.wait = gf100_bar_bar1_wait,
.bar2.vmm = gf100_bar_bar2_vmm,
.flush = g84_bar_flush,
};
int
gf100_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
return gf100_bar_new_(&gf100_bar_func, device, type, inst, pbar);
}
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: MIT */
#ifndef __GF100_BAR_H__
#define __GF100_BAR_H__
#define gf100_bar(p) container_of((p), struct gf100_bar, base)
#include "priv.h"
struct gf100_barN {
struct nvkm_memory *inst;
struct nvkm_vmm *vmm;
};
struct gf100_bar {
struct nvkm_bar base;
bool bar2_halve;
struct gf100_barN bar[2];
};
int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, enum nvkm_subdev_type,
int, struct nvkm_bar **);
void *gf100_bar_dtor(struct nvkm_bar *);
int gf100_bar_oneinit(struct nvkm_bar *);
void gf100_bar_bar1_init(struct nvkm_bar *);
void gf100_bar_bar1_wait(struct nvkm_bar *);
struct nvkm_vmm *gf100_bar_bar1_vmm(struct nvkm_bar *);
void gf100_bar_bar2_init(struct nvkm_bar *);
struct nvkm_vmm *gf100_bar_bar2_vmm(struct nvkm_bar *);
#endif
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* 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 AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#include "gf100.h"
static const struct nvkm_bar_func
gk20a_bar_func = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = gf100_bar_bar1_init,
.bar1.wait = gf100_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.flush = g84_bar_flush,
};
int
gk20a_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
int ret = gf100_bar_new_(&gk20a_bar_func, device, type, inst, pbar);
if (ret == 0)
(*pbar)->iomap_uncached = true;
return ret;
}
@@ -0,0 +1,66 @@
/*
* Copyright 2017 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.
*/
#include "gf100.h"
#include <subdev/timer.h>
void
gm107_bar_bar1_wait(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x001710) & 0x00000003))
break;
);
}
static void
gm107_bar_bar2_wait(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x001710) & 0x0000000c))
break;
);
}
static const struct nvkm_bar_func
gm107_bar_func = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = gf100_bar_bar1_init,
.bar1.fini = gf100_bar_bar1_fini,
.bar1.wait = gm107_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.bar2.init = gf100_bar_bar2_init,
.bar2.fini = gf100_bar_bar2_fini,
.bar2.wait = gm107_bar_bar2_wait,
.bar2.vmm = gf100_bar_bar2_vmm,
.flush = g84_bar_flush,
};
int
gm107_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
return gf100_bar_new_(&gm107_bar_func, device, type, inst, pbar);
}
@@ -0,0 +1,42 @@
/*
* Copyright 2017 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.
*/
#include "gf100.h"
static const struct nvkm_bar_func
gm20b_bar_func = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = gf100_bar_bar1_init,
.bar1.wait = gm107_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.flush = g84_bar_flush,
};
int
gm20b_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
int ret = gf100_bar_new_(&gm20b_bar_func, device, type, inst, pbar);
if (ret == 0)
(*pbar)->iomap_uncached = true;
return ret;
}
@@ -0,0 +1,255 @@
/*
* Copyright 2012 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "nv50.h"
#include <core/gpuobj.h>
#include <subdev/fb.h>
#include <subdev/mmu.h>
#include <subdev/timer.h>
static void
nv50_bar_flush(struct nvkm_bar *base)
{
struct nv50_bar *bar = nv50_bar(base);
struct nvkm_device *device = bar->base.subdev.device;
unsigned long flags;
spin_lock_irqsave(&bar->base.lock, flags);
nvkm_wr32(device, 0x00330c, 0x00000001);
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x00330c) & 0x00000002))
break;
);
spin_unlock_irqrestore(&bar->base.lock, flags);
}
struct nvkm_vmm *
nv50_bar_bar1_vmm(struct nvkm_bar *base)
{
return nv50_bar(base)->bar1_vmm;
}
void
nv50_bar_bar1_wait(struct nvkm_bar *base)
{
nvkm_bar_flush(base);
}
void
nv50_bar_bar1_fini(struct nvkm_bar *bar)
{
nvkm_wr32(bar->subdev.device, 0x001708, 0x00000000);
}
void
nv50_bar_bar1_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct nv50_bar *bar = nv50_bar(base);
nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4);
}
struct nvkm_vmm *
nv50_bar_bar2_vmm(struct nvkm_bar *base)
{
return nv50_bar(base)->bar2_vmm;
}
void
nv50_bar_bar2_fini(struct nvkm_bar *bar)
{
nvkm_wr32(bar->subdev.device, 0x00170c, 0x00000000);
}
void
nv50_bar_bar2_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct nv50_bar *bar = nv50_bar(base);
nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12);
nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12);
nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar2->node->offset >> 4);
}
void
nv50_bar_init(struct nvkm_bar *base)
{
struct nv50_bar *bar = nv50_bar(base);
struct nvkm_device *device = bar->base.subdev.device;
int i;
for (i = 0; i < 8; i++)
nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000);
}
int
nv50_bar_oneinit(struct nvkm_bar *base)
{
struct nv50_bar *bar = nv50_bar(base);
struct nvkm_device *device = bar->base.subdev.device;
static struct lock_class_key bar1_lock;
static struct lock_class_key bar2_lock;
u64 start, limit, size;
int ret;
ret = nvkm_gpuobj_new(device, 0x20000, 0, false, NULL, &bar->mem);
if (ret)
return ret;
ret = nvkm_gpuobj_new(device, bar->pgd_addr, 0, false, bar->mem,
&bar->pad);
if (ret)
return ret;
ret = nvkm_gpuobj_new(device, 0x4000, 0, false, bar->mem, &bar->pgd);
if (ret)
return ret;
/* BAR2 */
start = 0x0100000000ULL;
size = device->func->resource_size(device, NVKM_BAR2_INST);
if (!size)
return -ENOMEM;
limit = start + size;
ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0,
&bar2_lock, "bar2", &bar->bar2_vmm);
if (ret)
return ret;
atomic_inc(&bar->bar2_vmm->engref[NVKM_SUBDEV_BAR]);
bar->bar2_vmm->debug = bar->base.subdev.debug;
ret = nvkm_vmm_boot(bar->bar2_vmm);
if (ret)
return ret;
ret = nvkm_vmm_join(bar->bar2_vmm, bar->mem->memory);
if (ret)
return ret;
ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar2);
if (ret)
return ret;
nvkm_kmap(bar->bar2);
nvkm_wo32(bar->bar2, 0x00, 0x7fc00000);
nvkm_wo32(bar->bar2, 0x04, lower_32_bits(limit));
nvkm_wo32(bar->bar2, 0x08, lower_32_bits(start));
nvkm_wo32(bar->bar2, 0x0c, upper_32_bits(limit) << 24 |
upper_32_bits(start));
nvkm_wo32(bar->bar2, 0x10, 0x00000000);
nvkm_wo32(bar->bar2, 0x14, 0x00000000);
nvkm_done(bar->bar2);
bar->base.subdev.oneinit = true;
nvkm_bar_bar2_init(device);
/* BAR1 */
start = 0x0000000000ULL;
size = device->func->resource_size(device, NVKM_BAR1_FB);
if (!size)
return -ENOMEM;
limit = start + size;
ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0,
&bar1_lock, "bar1", &bar->bar1_vmm);
if (ret)
return ret;
atomic_inc(&bar->bar1_vmm->engref[NVKM_SUBDEV_BAR]);
bar->bar1_vmm->debug = bar->base.subdev.debug;
ret = nvkm_vmm_join(bar->bar1_vmm, bar->mem->memory);
if (ret)
return ret;
ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar1);
if (ret)
return ret;
nvkm_kmap(bar->bar1);
nvkm_wo32(bar->bar1, 0x00, 0x7fc00000);
nvkm_wo32(bar->bar1, 0x04, lower_32_bits(limit));
nvkm_wo32(bar->bar1, 0x08, lower_32_bits(start));
nvkm_wo32(bar->bar1, 0x0c, upper_32_bits(limit) << 24 |
upper_32_bits(start));
nvkm_wo32(bar->bar1, 0x10, 0x00000000);
nvkm_wo32(bar->bar1, 0x14, 0x00000000);
nvkm_done(bar->bar1);
return 0;
}
void *
nv50_bar_dtor(struct nvkm_bar *base)
{
struct nv50_bar *bar = nv50_bar(base);
if (bar->mem) {
nvkm_gpuobj_del(&bar->bar1);
nvkm_vmm_part(bar->bar1_vmm, bar->mem->memory);
nvkm_vmm_unref(&bar->bar1_vmm);
nvkm_gpuobj_del(&bar->bar2);
nvkm_vmm_part(bar->bar2_vmm, bar->mem->memory);
nvkm_vmm_unref(&bar->bar2_vmm);
nvkm_gpuobj_del(&bar->pgd);
nvkm_gpuobj_del(&bar->pad);
nvkm_gpuobj_del(&bar->mem);
}
return bar;
}
int
nv50_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, u32 pgd_addr, struct nvkm_bar **pbar)
{
struct nv50_bar *bar;
if (!(bar = kzalloc_obj(*bar)))
return -ENOMEM;
nvkm_bar_ctor(func, device, type, inst, &bar->base);
bar->pgd_addr = pgd_addr;
*pbar = &bar->base;
return 0;
}
static const struct nvkm_bar_func
nv50_bar_func = {
.dtor = nv50_bar_dtor,
.oneinit = nv50_bar_oneinit,
.init = nv50_bar_init,
.bar1.init = nv50_bar_bar1_init,
.bar1.fini = nv50_bar_bar1_fini,
.bar1.wait = nv50_bar_bar1_wait,
.bar1.vmm = nv50_bar_bar1_vmm,
.bar2.init = nv50_bar_bar2_init,
.bar2.fini = nv50_bar_bar2_fini,
.bar2.wait = nv50_bar_bar1_wait,
.bar2.vmm = nv50_bar_bar2_vmm,
.flush = nv50_bar_flush,
};
int
nv50_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
return nv50_bar_new_(&nv50_bar_func, device, type, inst, 0x1400, pbar);
}
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NV50_BAR_H__
#define __NV50_BAR_H__
#define nv50_bar(p) container_of((p), struct nv50_bar, base)
#include "priv.h"
struct nv50_bar {
struct nvkm_bar base;
u32 pgd_addr;
struct nvkm_gpuobj *mem;
struct nvkm_gpuobj *pad;
struct nvkm_gpuobj *pgd;
struct nvkm_vmm *bar1_vmm;
struct nvkm_gpuobj *bar1;
struct nvkm_vmm *bar2_vmm;
struct nvkm_gpuobj *bar2;
};
int nv50_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, enum nvkm_subdev_type,
int, u32 pgd_addr, struct nvkm_bar **);
void *nv50_bar_dtor(struct nvkm_bar *);
int nv50_bar_oneinit(struct nvkm_bar *);
void nv50_bar_init(struct nvkm_bar *);
void nv50_bar_bar1_init(struct nvkm_bar *);
void nv50_bar_bar1_wait(struct nvkm_bar *);
struct nvkm_vmm *nv50_bar_bar1_vmm(struct nvkm_bar *);
void nv50_bar_bar2_init(struct nvkm_bar *);
struct nvkm_vmm *nv50_bar_bar2_vmm(struct nvkm_bar *);
#endif
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_BAR_PRIV_H__
#define __NVKM_BAR_PRIV_H__
#define nvkm_bar(p) container_of((p), struct nvkm_bar, subdev)
#include <subdev/bar.h>
int r535_bar_new_(const struct nvkm_bar_func *,
struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_bar **);
void nvkm_bar_ctor(const struct nvkm_bar_func *, struct nvkm_device *,
enum nvkm_subdev_type, int, struct nvkm_bar *);
struct nvkm_bar_func {
void *(*dtor)(struct nvkm_bar *);
int (*oneinit)(struct nvkm_bar *);
void (*init)(struct nvkm_bar *);
struct {
void (*init)(struct nvkm_bar *);
void (*fini)(struct nvkm_bar *);
void (*wait)(struct nvkm_bar *);
struct nvkm_vmm *(*vmm)(struct nvkm_bar *);
} bar1, bar2;
void (*flush)(struct nvkm_bar *);
};
void nv50_bar_bar1_fini(struct nvkm_bar *);
void nv50_bar_bar2_fini(struct nvkm_bar *);
void g84_bar_flush(struct nvkm_bar *);
void gf100_bar_bar1_fini(struct nvkm_bar *);
void gf100_bar_bar2_fini(struct nvkm_bar *);
void gm107_bar_bar1_wait(struct nvkm_bar *);
#endif
@@ -0,0 +1,103 @@
/*
* Copyright 2018 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.
*/
#include "gf100.h"
#include <core/memory.h>
#include <subdev/gsp.h>
#include <subdev/timer.h>
static void
tu102_bar_bar2_wait(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0xb80f50) & 0x0000000c))
break;
);
}
static void
tu102_bar_bar2_fini(struct nvkm_bar *bar)
{
nvkm_mask(bar->subdev.device, 0xb80f48, 0x80000000, 0x00000000);
}
static void
tu102_bar_bar2_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct gf100_bar *bar = gf100_bar(base);
u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
if (bar->bar2_halve)
addr |= 0x40000000;
nvkm_wr32(device, 0xb80f48, 0x80000000 | addr);
}
static void
tu102_bar_bar1_wait(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0xb80f50) & 0x00000003))
break;
);
}
static void
tu102_bar_bar1_fini(struct nvkm_bar *bar)
{
nvkm_mask(bar->subdev.device, 0xb80f40, 0x80000000, 0x00000000);
}
static void
tu102_bar_bar1_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct gf100_bar *bar = gf100_bar(base);
const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
nvkm_wr32(device, 0xb80f40, 0x80000000 | addr);
}
static const struct nvkm_bar_func
tu102_bar = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = tu102_bar_bar1_init,
.bar1.fini = tu102_bar_bar1_fini,
.bar1.wait = tu102_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.bar2.init = tu102_bar_bar2_init,
.bar2.fini = tu102_bar_bar2_fini,
.bar2.wait = tu102_bar_bar2_wait,
.bar2.vmm = gf100_bar_bar2_vmm,
.flush = g84_bar_flush,
};
int
tu102_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_bar **pbar)
{
if (nvkm_gsp_rm(device->gsp))
return r535_bar_new_(&tu102_bar, device, type, inst, pbar);
return gf100_bar_new_(&tu102_bar, device, type, inst, pbar);
}