drm/nouveau/acr/tu10x: initial support

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2020-01-15 06:34:22 +10:00
parent edec7149cb
commit 3fa8fe1572
6 changed files with 229 additions and 0 deletions

View File

@ -62,6 +62,7 @@ int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
int gp108_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
int gp10b_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
int tu102_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
struct nvkm_acr_lsfw {
const struct nvkm_acr_lsf_func *func;

View File

@ -2462,6 +2462,7 @@ nv140_chipset = {
static const struct nvkm_device_chip
nv162_chipset = {
.name = "TU102",
.acr = tu102_acr_new,
.bar = tu102_bar_new,
.bios = nvkm_bios_new,
.bus = gf100_bus_new,
@ -2498,6 +2499,7 @@ nv162_chipset = {
static const struct nvkm_device_chip
nv164_chipset = {
.name = "TU104",
.acr = tu102_acr_new,
.bar = tu102_bar_new,
.bios = nvkm_bios_new,
.bus = gf100_bus_new,
@ -2535,6 +2537,7 @@ nv164_chipset = {
static const struct nvkm_device_chip
nv166_chipset = {
.name = "TU106",
.acr = tu102_acr_new,
.bar = tu102_bar_new,
.bios = nvkm_bios_new,
.bus = gf100_bus_new,

View File

@ -7,3 +7,4 @@ nvkm-y += nvkm/subdev/acr/gm20b.o
nvkm-y += nvkm/subdev/acr/gp102.o
nvkm-y += nvkm/subdev/acr/gp108.o
nvkm-y += nvkm/subdev/acr/gp10b.o
nvkm-y += nvkm/subdev/acr/tu102.o

View File

@ -215,6 +215,12 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
u32 wpr_size = 0;
int ret, i;
if (list_empty(&acr->hsfw)) {
nvkm_debug(subdev, "No HSFW(s)\n");
nvkm_acr_cleanup(acr);
return 0;
}
/* Determine layout/size of WPR image up-front, as we need to know
* it to allocate memory before we begin constructing it.
*/

View File

@ -0,0 +1,215 @@
/*
* Copyright 2019 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 "priv.h"
#include <core/firmware.h>
#include <core/memory.h>
#include <subdev/gsp.h>
#include <subdev/pmu.h>
#include <engine/sec2.h>
#include <nvfw/acr.h>
static int
tu102_acr_init(struct nvkm_acr *acr)
{
int ret = nvkm_acr_hsf_boot(acr, "AHESASC");
if (ret)
return ret;
return nvkm_acr_hsf_boot(acr, "ASB");
}
static int
tu102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos)
{
struct nvkm_acr_lsfw *lsfw;
u32 offset = 0;
int ret;
/*XXX: shared sub-WPR headers, fill terminator for now. */
nvkm_wo32(acr->wpr, 0x200, 0xffffffff);
/* Fill per-LSF structures. */
list_for_each_entry(lsfw, &acr->lsfw, head) {
struct lsf_signature_v1 *sig = (void *)lsfw->sig->data;
struct wpr_header_v1 hdr = {
.falcon_id = lsfw->id,
.lsb_offset = lsfw->offset.lsb,
.bootstrap_owner = NVKM_ACR_LSF_GSPLITE,
.lazy_bootstrap = 1,
.bin_version = sig->version,
.status = WPR_HEADER_V1_STATUS_COPY,
};
/* Write WPR header. */
nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
offset += sizeof(hdr);
/* Write LSB header. */
ret = gp102_acr_wpr_build_lsb(acr, lsfw);
if (ret)
return ret;
/* Write ucode image. */
nvkm_wobj(acr->wpr, lsfw->offset.img,
lsfw->img.data,
lsfw->img.size);
/* Write bootloader data. */
lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw);
}
/* Finalise WPR. */
nvkm_wo32(acr->wpr, offset, WPR_HEADER_V1_FALCON_ID_INVALID);
return 0;
}
static int
tu102_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
{
return gm200_acr_hsfw_boot(acr, hsf, 0, 0);
}
static int
tu102_acr_hsfw_nofw(struct nvkm_acr *acr, const char *bl, const char *fw,
const char *name, int version,
const struct nvkm_acr_hsf_fwif *fwif)
{
return 0;
}
MODULE_FIRMWARE("nvidia/tu102/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/tu102/acr/ucode_unload.bin");
MODULE_FIRMWARE("nvidia/tu104/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/tu104/acr/ucode_unload.bin");
MODULE_FIRMWARE("nvidia/tu106/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/tu106/acr/ucode_unload.bin");
static const struct nvkm_acr_hsf_fwif
tu102_acr_unload_fwif[] = {
{ 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 },
{ -1, tu102_acr_hsfw_nofw },
{}
};
static int
tu102_acr_asb_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
{
return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->gsp->falcon);
}
static const struct nvkm_acr_hsf_func
tu102_acr_asb_0 = {
.load = tu102_acr_asb_load,
.boot = tu102_acr_hsfw_boot,
.bld = gp108_acr_hsfw_bld,
};
MODULE_FIRMWARE("nvidia/tu102/acr/ucode_asb.bin");
MODULE_FIRMWARE("nvidia/tu104/acr/ucode_asb.bin");
MODULE_FIRMWARE("nvidia/tu106/acr/ucode_asb.bin");
static const struct nvkm_acr_hsf_fwif
tu102_acr_asb_fwif[] = {
{ 0, nvkm_acr_hsfw_load, &tu102_acr_asb_0 },
{ -1, tu102_acr_hsfw_nofw },
{}
};
static const struct nvkm_acr_hsf_func
tu102_acr_ahesasc_0 = {
.load = gp102_acr_load_load,
.boot = tu102_acr_hsfw_boot,
.bld = gp108_acr_hsfw_bld,
};
MODULE_FIRMWARE("nvidia/tu102/acr/bl.bin");
MODULE_FIRMWARE("nvidia/tu102/acr/ucode_ahesasc.bin");
MODULE_FIRMWARE("nvidia/tu104/acr/bl.bin");
MODULE_FIRMWARE("nvidia/tu104/acr/ucode_ahesasc.bin");
MODULE_FIRMWARE("nvidia/tu106/acr/bl.bin");
MODULE_FIRMWARE("nvidia/tu106/acr/ucode_ahesasc.bin");
static const struct nvkm_acr_hsf_fwif
tu102_acr_ahesasc_fwif[] = {
{ 0, nvkm_acr_hsfw_load, &tu102_acr_ahesasc_0 },
{ -1, tu102_acr_hsfw_nofw },
{}
};
static const struct nvkm_acr_func
tu102_acr = {
.ahesasc = tu102_acr_ahesasc_fwif,
.asb = tu102_acr_asb_fwif,
.unload = tu102_acr_unload_fwif,
.wpr_parse = gp102_acr_wpr_parse,
.wpr_layout = gp102_acr_wpr_layout,
.wpr_alloc = gp102_acr_wpr_alloc,
.wpr_patch = gp102_acr_wpr_patch,
.wpr_build = tu102_acr_wpr_build,
.wpr_check = gm200_acr_wpr_check,
.init = tu102_acr_init,
};
static int
tu102_acr_load(struct nvkm_acr *acr, int version,
const struct nvkm_acr_fwif *fwif)
{
struct nvkm_subdev *subdev = &acr->subdev;
const struct nvkm_acr_hsf_fwif *hsfwif;
hsfwif = nvkm_firmware_load(subdev, fwif->func->ahesasc, "AcrAHESASC",
acr, "acr/bl", "acr/ucode_ahesasc",
"AHESASC");
if (IS_ERR(hsfwif))
return PTR_ERR(hsfwif);
hsfwif = nvkm_firmware_load(subdev, fwif->func->asb, "AcrASB",
acr, "acr/bl", "acr/ucode_asb", "ASB");
if (IS_ERR(hsfwif))
return PTR_ERR(hsfwif);
hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload",
acr, "acr/unload_bl", "acr/ucode_unload",
"unload");
if (IS_ERR(hsfwif))
return PTR_ERR(hsfwif);
return 0;
}
static const struct nvkm_acr_fwif
tu102_acr_fwif[] = {
{ 0, tu102_acr_load, &tu102_acr },
{}
};
int
tu102_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr)
{
return nvkm_acr_new_(tu102_acr_fwif, device, index, pacr);
}

View File

@ -48,3 +48,6 @@ gv100_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
}
MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin");
MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin");