mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 06:10:56 +00:00
drm/nouveau/fb/ga102: load and boot VPR scrubber FW
v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Gourav Samaiya <gsamaiya@nvidia.com>
This commit is contained in:
parent
21876b0e42
commit
a51c69ee74
19 changed files with 551 additions and 5 deletions
|
@ -17,6 +17,20 @@ struct nvfw_hs_header {
|
|||
|
||||
const struct nvfw_hs_header *nvfw_hs_header(struct nvkm_subdev *, const void *);
|
||||
|
||||
struct nvfw_hs_header_v2 {
|
||||
u32 sig_prod_offset;
|
||||
u32 sig_prod_size;
|
||||
u32 patch_loc;
|
||||
u32 patch_sig;
|
||||
u32 meta_data_offset;
|
||||
u32 meta_data_size;
|
||||
u32 num_sig;
|
||||
u32 header_offset;
|
||||
u32 header_size;
|
||||
};
|
||||
|
||||
const struct nvfw_hs_header_v2 *nvfw_hs_header_v2(struct nvkm_subdev *, const void *);
|
||||
|
||||
struct nvfw_hs_load_header {
|
||||
u32 non_sec_code_off;
|
||||
u32 non_sec_code_size;
|
||||
|
@ -28,4 +42,18 @@ struct nvfw_hs_load_header {
|
|||
|
||||
const struct nvfw_hs_load_header *
|
||||
nvfw_hs_load_header(struct nvkm_subdev *, const void *);
|
||||
|
||||
struct nvfw_hs_load_header_v2 {
|
||||
u32 os_code_offset;
|
||||
u32 os_code_size;
|
||||
u32 os_data_offset;
|
||||
u32 os_data_size;
|
||||
u32 num_apps;
|
||||
struct {
|
||||
u32 offset;
|
||||
u32 size;
|
||||
} app[0];
|
||||
};
|
||||
|
||||
const struct nvfw_hs_load_header_v2 *nvfw_hs_load_header_v2(struct nvkm_subdev *, const void *);
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,13 @@ struct nvkm_falcon_func_pio {
|
|||
void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len);
|
||||
};
|
||||
|
||||
struct nvkm_falcon_func_dma {
|
||||
int (*init)(struct nvkm_falcon *, u64 dma_addr, int xfer_len,
|
||||
enum nvkm_falcon_mem, bool sec, u32 *cmd);
|
||||
void (*xfer)(struct nvkm_falcon *, u32 mem_base, u32 dma_base, u32 cmd);
|
||||
bool (*done)(struct nvkm_falcon *);
|
||||
};
|
||||
|
||||
int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner,
|
||||
const char *name, u32 addr, struct nvkm_falcon *);
|
||||
void nvkm_falcon_dtor(struct nvkm_falcon *);
|
||||
|
@ -39,6 +46,8 @@ int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 por
|
|||
enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec);
|
||||
int nvkm_falcon_pio_rd(struct nvkm_falcon *, u8 port, enum nvkm_falcon_mem type, u32 mem_base,
|
||||
const u8 *img, u32 img_base, int len);
|
||||
int nvkm_falcon_dma_wr(struct nvkm_falcon *, const u8 *img, u64 dma_addr, u32 dma_base,
|
||||
enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec);
|
||||
|
||||
int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
|
||||
int gm200_flcn_disable(struct nvkm_falcon *);
|
||||
|
@ -52,6 +61,10 @@ void gm200_flcn_tracepc(struct nvkm_falcon *);
|
|||
int gp102_flcn_reset_eng(struct nvkm_falcon *);
|
||||
extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio;
|
||||
|
||||
int ga102_flcn_reset_prep(struct nvkm_falcon *);
|
||||
int ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
|
||||
extern const struct nvkm_falcon_func_dma ga102_flcn_dma;
|
||||
|
||||
void nvkm_falcon_v1_load_imem(struct nvkm_falcon *,
|
||||
void *, u32, u32, u16, u8, bool);
|
||||
void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
|
||||
|
@ -87,6 +100,9 @@ struct nvkm_falcon_fw {
|
|||
u32 sig_size;
|
||||
int sig_nr;
|
||||
u8 *sigs;
|
||||
u32 fuse_ver;
|
||||
u32 engine_id;
|
||||
u32 ucode_id;
|
||||
|
||||
u32 nmem_base_img;
|
||||
u32 nmem_base;
|
||||
|
@ -117,6 +133,9 @@ int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, st
|
|||
int nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *, const char *name,
|
||||
struct nvkm_subdev *, const char *bl, const char *img, int ver,
|
||||
struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw);
|
||||
int nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *, const char *name,
|
||||
struct nvkm_subdev *, const char *img, int ver, struct nvkm_falcon *,
|
||||
struct nvkm_falcon_fw *);
|
||||
int nvkm_falcon_fw_sign(struct nvkm_falcon_fw *, u32 sig_base_img, u32 sig_size, const u8 *sigs,
|
||||
int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg);
|
||||
int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *);
|
||||
|
@ -132,6 +151,12 @@ int gm200_flcn_fw_reset(struct nvkm_falcon_fw *);
|
|||
int gm200_flcn_fw_load(struct nvkm_falcon_fw *);
|
||||
int gm200_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32);
|
||||
|
||||
int ga100_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *);
|
||||
|
||||
extern const struct nvkm_falcon_fw_func ga102_flcn_fw;
|
||||
int ga102_flcn_fw_load(struct nvkm_falcon_fw *);
|
||||
int ga102_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32);
|
||||
|
||||
#define FLCNFW_PRINTK(f,l,p,fmt,a...) FLCN_PRINTK((f)->falcon, l, p, "%s: "fmt, (f)->fw.name, ##a)
|
||||
#define FLCNFW_DBG(f,fmt,a...) FLCNFW_PRINTK((f), DEBUG, info, fmt"\n", ##a)
|
||||
#define FLCNFW_ERR(f,fmt,a...) FLCNFW_PRINTK((f), ERROR, err, fmt"\n", ##a)
|
||||
|
|
|
@ -19,6 +19,7 @@ struct nvkm_falcon {
|
|||
struct nvkm_subdev *owner;
|
||||
const char *name;
|
||||
u32 addr;
|
||||
u32 addr2;
|
||||
|
||||
struct mutex mutex;
|
||||
struct mutex dmem_mutex;
|
||||
|
@ -59,8 +60,10 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *,
|
|||
struct nvkm_falcon_func {
|
||||
int (*disable)(struct nvkm_falcon *);
|
||||
int (*enable)(struct nvkm_falcon *);
|
||||
u32 addr2;
|
||||
bool reset_pmc;
|
||||
int (*reset_eng)(struct nvkm_falcon *);
|
||||
int (*reset_prep)(struct nvkm_falcon *);
|
||||
int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *);
|
||||
|
||||
u32 debug;
|
||||
|
@ -69,7 +72,10 @@ struct nvkm_falcon_func {
|
|||
bool bind_intr;
|
||||
|
||||
const struct nvkm_falcon_func_pio *imem_pio;
|
||||
const struct nvkm_falcon_func_dma *imem_dma;
|
||||
|
||||
const struct nvkm_falcon_func_pio *dmem_pio;
|
||||
const struct nvkm_falcon_func_dma *dmem_dma;
|
||||
|
||||
u32 emem_addr;
|
||||
const struct nvkm_falcon_func_pio *emem_pio;
|
||||
|
|
|
@ -12,4 +12,5 @@ struct nvkm_nvdec {
|
|||
};
|
||||
|
||||
int gm107_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_nvdec **);
|
||||
int ga102_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_nvdec **);
|
||||
#endif
|
||||
|
|
|
@ -2615,6 +2615,7 @@ nv172_chipset = {
|
|||
.disp = { 0x00000001, ga102_disp_new },
|
||||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
|
@ -2639,6 +2640,7 @@ nv173_chipset = {
|
|||
.disp = { 0x00000001, ga102_disp_new },
|
||||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
|
@ -2663,6 +2665,7 @@ nv174_chipset = {
|
|||
.disp = { 0x00000001, ga102_disp_new },
|
||||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
|
@ -2687,6 +2690,7 @@ nv176_chipset = {
|
|||
.disp = { 0x00000001, ga102_disp_new },
|
||||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
|
@ -2711,6 +2715,7 @@ nv177_chipset = {
|
|||
.disp = { 0x00000001, ga102_disp_new },
|
||||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
};
|
||||
|
||||
struct nvkm_subdev *
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
nvkm-y += nvkm/engine/nvdec/base.o
|
||||
nvkm-y += nvkm/engine/nvdec/gm107.o
|
||||
nvkm-y += nvkm/engine/nvdec/ga102.o
|
||||
|
|
|
@ -37,7 +37,7 @@ nvkm_nvdec = {
|
|||
|
||||
int
|
||||
nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device,
|
||||
enum nvkm_subdev_type type, int inst, struct nvkm_nvdec **pnvdec)
|
||||
enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_nvdec **pnvdec)
|
||||
{
|
||||
struct nvkm_nvdec *nvdec;
|
||||
int ret;
|
||||
|
@ -57,5 +57,5 @@ nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device,
|
|||
nvdec->func = fwif->func;
|
||||
|
||||
return nvkm_falcon_ctor(nvdec->func->flcn, &nvdec->engine.subdev,
|
||||
nvdec->engine.subdev.name, 0, &nvdec->falcon);
|
||||
nvdec->engine.subdev.name, addr, &nvdec->falcon);
|
||||
};
|
||||
|
|
61
drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c
Normal file
61
drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2021 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 <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
|
||||
static const struct nvkm_falcon_func
|
||||
ga102_nvdec_flcn = {
|
||||
.disable = gm200_flcn_disable,
|
||||
.enable = gm200_flcn_enable,
|
||||
.addr2 = 0x1c00,
|
||||
.reset_pmc = true,
|
||||
.reset_prep = ga102_flcn_reset_prep,
|
||||
.reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing,
|
||||
.imem_dma = &ga102_flcn_dma,
|
||||
.dmem_dma = &ga102_flcn_dma,
|
||||
};
|
||||
|
||||
static const struct nvkm_nvdec_func
|
||||
ga102_nvdec = {
|
||||
.flcn = &ga102_nvdec_flcn,
|
||||
};
|
||||
|
||||
static int
|
||||
ga102_nvdec_nofw(struct nvkm_nvdec *nvdec, int ver, const struct nvkm_nvdec_fwif *fwif)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nvkm_nvdec_fwif
|
||||
ga102_nvdec_fwif[] = {
|
||||
{ -1, ga102_nvdec_nofw, &ga102_nvdec },
|
||||
{}
|
||||
};
|
||||
|
||||
int
|
||||
ga102_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_nvdec **pnvdec)
|
||||
{
|
||||
return nvkm_nvdec_new_(ga102_nvdec_fwif, device, type, inst, 0x848000, pnvdec);
|
||||
}
|
|
@ -54,5 +54,5 @@ int
|
|||
gm107_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_nvdec **pnvdec)
|
||||
{
|
||||
return nvkm_nvdec_new_(gm107_nvdec_fwif, device, type, inst, pnvdec);
|
||||
return nvkm_nvdec_new_(gm107_nvdec_fwif, device, type, inst, 0, pnvdec);
|
||||
}
|
||||
|
|
|
@ -15,5 +15,5 @@ struct nvkm_nvdec_fwif {
|
|||
};
|
||||
|
||||
int nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *,
|
||||
enum nvkm_subdev_type, int, struct nvkm_nvdec **);
|
||||
enum nvkm_subdev_type, int, u32 addr, struct nvkm_nvdec **);
|
||||
#endif
|
||||
|
|
|
@ -8,3 +8,5 @@ nvkm-y += nvkm/falcon/v1.o
|
|||
|
||||
nvkm-y += nvkm/falcon/gm200.o
|
||||
nvkm-y += nvkm/falcon/gp102.o
|
||||
nvkm-y += nvkm/falcon/ga100.o
|
||||
nvkm-y += nvkm/falcon/ga102.o
|
||||
|
|
|
@ -25,6 +25,82 @@
|
|||
#include <subdev/timer.h>
|
||||
#include <subdev/top.h>
|
||||
|
||||
static const struct nvkm_falcon_func_dma *
|
||||
nvkm_falcon_dma(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base)
|
||||
{
|
||||
switch (*mem_type) {
|
||||
case IMEM: return falcon->func->imem_dma;
|
||||
case DMEM: return falcon->func->dmem_dma;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_falcon_dma_wr(struct nvkm_falcon *falcon, const u8 *img, u64 dma_addr, u32 dma_base,
|
||||
enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec)
|
||||
{
|
||||
const struct nvkm_falcon_func_dma *dma = nvkm_falcon_dma(falcon, &mem_type, &mem_base);
|
||||
const char *type = nvkm_falcon_mem(mem_type);
|
||||
const int dmalen = 256;
|
||||
u32 dma_start = 0;
|
||||
u32 dst, src, cmd;
|
||||
int ret, i;
|
||||
|
||||
if (WARN_ON(!dma->xfer))
|
||||
return -EINVAL;
|
||||
|
||||
if (mem_type == DMEM) {
|
||||
dma_start = dma_base;
|
||||
dma_addr += dma_base;
|
||||
}
|
||||
|
||||
FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x (%010llx %08x)",
|
||||
type, mem_base, len, dma_base, dma_addr - dma_base, dma_start);
|
||||
if (WARN_ON(!len || (len & (dmalen - 1))))
|
||||
return -EINVAL;
|
||||
|
||||
ret = dma->init(falcon, dma_addr, dmalen, mem_type, sec, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dst = mem_base;
|
||||
src = dma_base;
|
||||
if (len) {
|
||||
while (len >= dmalen) {
|
||||
dma->xfer(falcon, dst, src - dma_start, cmd);
|
||||
|
||||
if (img && nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
|
||||
for (i = 0; i < dmalen; i += 4, mem_base += 4) {
|
||||
const int w = 8, x = (i / 4) % w;
|
||||
|
||||
if (x == 0)
|
||||
printk(KERN_INFO "%s %08x <-", type, mem_base);
|
||||
printk(KERN_CONT " %08x", *(u32 *)(img + src + i));
|
||||
if (x == (w - 1) || ((i + 4) == dmalen))
|
||||
printk(KERN_CONT " <- %08x+%08x", dma_base,
|
||||
src + i - dma_base - (x * 4));
|
||||
if (i == (7 * 4))
|
||||
printk(KERN_CONT " *");
|
||||
}
|
||||
}
|
||||
|
||||
if (nvkm_msec(falcon->owner->device, 2000,
|
||||
if (dma->done(falcon))
|
||||
break;
|
||||
) < 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
src += dmalen;
|
||||
dst += dmalen;
|
||||
len -= dmalen;
|
||||
}
|
||||
WARN_ON(len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nvkm_falcon_func_pio *
|
||||
nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base)
|
||||
{
|
||||
|
@ -239,6 +315,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
|
|||
falcon->owner = subdev;
|
||||
falcon->name = name;
|
||||
falcon->addr = addr;
|
||||
falcon->addr2 = func->addr2;
|
||||
mutex_init(&falcon->mutex);
|
||||
mutex_init(&falcon->dmem_mutex);
|
||||
return 0;
|
||||
|
|
|
@ -294,3 +294,61 @@ nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name,
|
|||
nvkm_firmware_put(blob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *func, const char *name,
|
||||
struct nvkm_subdev *subdev, const char *img, int ver,
|
||||
struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw)
|
||||
{
|
||||
const struct nvfw_bin_hdr *hdr;
|
||||
const struct nvfw_hs_header_v2 *hshdr;
|
||||
const struct nvfw_hs_load_header_v2 *lhdr;
|
||||
const struct firmware *blob;
|
||||
u32 loc, sig, cnt, *meta;
|
||||
int ret;
|
||||
|
||||
ret = nvkm_firmware_load_name(subdev, img, "", ver, &blob);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdr = nvfw_bin_hdr(subdev, blob->data);
|
||||
hshdr = nvfw_hs_header_v2(subdev, blob->data + hdr->header_offset);
|
||||
meta = (u32 *)(blob->data + hshdr->meta_data_offset);
|
||||
loc = *(u32 *)(blob->data + hshdr->patch_loc);
|
||||
sig = *(u32 *)(blob->data + hshdr->patch_sig);
|
||||
cnt = *(u32 *)(blob->data + hshdr->num_sig);
|
||||
|
||||
ret = nvkm_falcon_fw_ctor(func, name, subdev->device, true,
|
||||
blob->data + hdr->data_offset, hdr->data_size, falcon, fw);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size / cnt, blob->data,
|
||||
cnt, hshdr->sig_prod_offset + sig, 0, 0);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
lhdr = nvfw_hs_load_header_v2(subdev, blob->data + hshdr->header_offset);
|
||||
|
||||
fw->imem_base_img = lhdr->app[0].offset;
|
||||
fw->imem_base = 0;
|
||||
fw->imem_size = lhdr->app[0].size;
|
||||
|
||||
fw->dmem_base_img = lhdr->os_data_offset;
|
||||
fw->dmem_base = 0;
|
||||
fw->dmem_size = lhdr->os_data_size;
|
||||
fw->dmem_sign = loc - lhdr->os_data_offset;
|
||||
|
||||
fw->boot_addr = lhdr->app[0].offset;
|
||||
|
||||
fw->fuse_ver = meta[0];
|
||||
fw->engine_id = meta[1];
|
||||
fw->ucode_id = meta[2];
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
nvkm_falcon_fw_dtor(fw);
|
||||
|
||||
nvkm_firmware_put(blob);
|
||||
return ret;
|
||||
}
|
||||
|
|
62
drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c
Normal file
62
drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2021 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"
|
||||
|
||||
int
|
||||
ga100_flcn_fw_signature(struct nvkm_falcon_fw *fw, u32 *src_base_src)
|
||||
{
|
||||
struct nvkm_falcon *falcon = fw->falcon;
|
||||
struct nvkm_device *device = falcon->owner->device;
|
||||
u32 reg_fuse_version;
|
||||
int idx;
|
||||
|
||||
FLCN_DBG(falcon, "brom: %08x %08x", fw->engine_id, fw->ucode_id);
|
||||
FLCN_DBG(falcon, "fuse_version: %d", fw->fuse_ver);
|
||||
|
||||
if (fw->engine_id & 0x00000001) {
|
||||
reg_fuse_version = nvkm_rd32(device, 0x824140 + (fw->ucode_id - 1) * 4);
|
||||
} else
|
||||
if (fw->engine_id & 0x00000004) {
|
||||
reg_fuse_version = nvkm_rd32(device, 0x824100 + (fw->ucode_id - 1) * 4);
|
||||
} else
|
||||
if (fw->engine_id & 0x00000400) {
|
||||
reg_fuse_version = nvkm_rd32(device, 0x8241c0 + (fw->ucode_id - 1) * 4);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
FLCN_DBG(falcon, "reg_fuse_version: %08x", reg_fuse_version);
|
||||
if (reg_fuse_version) {
|
||||
reg_fuse_version = fls(reg_fuse_version);
|
||||
FLCN_DBG(falcon, "reg_fuse_version: %d", reg_fuse_version);
|
||||
|
||||
if (WARN_ON(fw->fuse_ver < reg_fuse_version))
|
||||
return -EINVAL;
|
||||
|
||||
idx = fw->fuse_ver - reg_fuse_version;
|
||||
} else {
|
||||
idx = fw->sig_nr - 1;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
134
drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c
Normal file
134
drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2022 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 <subdev/mc.h>
|
||||
#include <subdev/timer.h>
|
||||
|
||||
static bool
|
||||
ga102_flcn_dma_done(struct nvkm_falcon *falcon)
|
||||
{
|
||||
return !!(nvkm_falcon_rd32(falcon, 0x118) & 0x00000002);
|
||||
}
|
||||
|
||||
static void
|
||||
ga102_flcn_dma_xfer(struct nvkm_falcon *falcon, u32 mem_base, u32 dma_base, u32 cmd)
|
||||
{
|
||||
nvkm_falcon_wr32(falcon, 0x114, mem_base);
|
||||
nvkm_falcon_wr32(falcon, 0x11c, dma_base);
|
||||
nvkm_falcon_wr32(falcon, 0x118, cmd);
|
||||
}
|
||||
|
||||
static int
|
||||
ga102_flcn_dma_init(struct nvkm_falcon *falcon, u64 dma_addr, int xfer_len,
|
||||
enum nvkm_falcon_mem mem_type, bool sec, u32 *cmd)
|
||||
{
|
||||
*cmd = (ilog2(xfer_len) - 2) << 8;
|
||||
if (mem_type == IMEM)
|
||||
*cmd |= 0x00000010;
|
||||
if (sec)
|
||||
*cmd |= 0x00000004;
|
||||
|
||||
nvkm_falcon_wr32(falcon, 0x110, dma_addr >> 8);
|
||||
nvkm_falcon_wr32(falcon, 0x128, 0x00000000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct nvkm_falcon_func_dma
|
||||
ga102_flcn_dma = {
|
||||
.init = ga102_flcn_dma_init,
|
||||
.xfer = ga102_flcn_dma_xfer,
|
||||
.done = ga102_flcn_dma_done,
|
||||
};
|
||||
|
||||
int
|
||||
ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
|
||||
{
|
||||
nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
|
||||
|
||||
if (nvkm_msec(falcon->owner->device, 20,
|
||||
if (!(nvkm_falcon_rd32(falcon, 0x0f4) & 0x00001000))
|
||||
break;
|
||||
) < 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ga102_flcn_reset_prep(struct nvkm_falcon *falcon)
|
||||
{
|
||||
const u32 addr2 = (falcon->owner->type != NVKM_ENGINE_NVDEC) ? 0x530 : 0x930;
|
||||
|
||||
if (nvkm_msec(falcon->owner->device, 10,
|
||||
if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x1ec) & 0x00000003) == 0x00000001 &&
|
||||
(nvkm_falcon_rd32(falcon, addr2) & 0x00000008) == 0x00000008)
|
||||
break;
|
||||
) < 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ga102_flcn_fw_boot(struct nvkm_falcon_fw *fw, u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr)
|
||||
{
|
||||
struct nvkm_falcon *falcon = fw->falcon;
|
||||
|
||||
nvkm_falcon_wr32(falcon, falcon->addr2 + 0x210, fw->dmem_sign);
|
||||
nvkm_falcon_wr32(falcon, falcon->addr2 + 0x19c, fw->engine_id);
|
||||
nvkm_falcon_wr32(falcon, falcon->addr2 + 0x198, fw->ucode_id);
|
||||
nvkm_falcon_wr32(falcon, falcon->addr2 + 0x180, 0x00000001);
|
||||
|
||||
return gm200_flcn_fw_boot(fw, mbox0, mbox1, mbox0_ok, irqsclr);
|
||||
}
|
||||
|
||||
int
|
||||
ga102_flcn_fw_load(struct nvkm_falcon_fw *fw)
|
||||
{
|
||||
struct nvkm_falcon *falcon = fw->falcon;
|
||||
int ret = 0;
|
||||
|
||||
nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080);
|
||||
nvkm_falcon_wr32(falcon, 0x10c, 0x00000000);
|
||||
nvkm_falcon_mask(falcon, 0x600, 0x00010007, (0 << 16) | (1 << 2) | 1);
|
||||
|
||||
ret = nvkm_falcon_dma_wr(falcon, fw->fw.img, fw->fw.phys, fw->imem_base_img,
|
||||
IMEM, fw->imem_base, fw->imem_size, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvkm_falcon_dma_wr(falcon, fw->fw.img, fw->fw.phys, fw->dmem_base_img,
|
||||
DMEM, fw->dmem_base, fw->dmem_size, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct nvkm_falcon_fw_func
|
||||
ga102_flcn_fw = {
|
||||
.signature = ga100_flcn_fw_signature,
|
||||
.reset = gm200_flcn_fw_reset,
|
||||
.load = ga102_flcn_fw_load,
|
||||
.boot = ga102_flcn_fw_boot,
|
||||
};
|
|
@ -171,8 +171,15 @@ gm200_flcn_disable(struct nvkm_falcon *falcon)
|
|||
nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000);
|
||||
nvkm_falcon_wr32(falcon, 0x014, 0xffffffff);
|
||||
|
||||
if (falcon->func->reset_pmc)
|
||||
if (falcon->func->reset_pmc) {
|
||||
if (falcon->func->reset_prep) {
|
||||
ret = falcon->func->reset_prep(falcon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
|
||||
}
|
||||
|
||||
if (falcon->func->reset_eng) {
|
||||
ret = falcon->func->reset_eng(falcon);
|
||||
|
|
|
@ -66,6 +66,14 @@ gp102_flcn_emem_pio = {
|
|||
int
|
||||
gp102_flcn_reset_eng(struct nvkm_falcon *falcon)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (falcon->func->reset_prep) {
|
||||
ret = falcon->func->reset_prep(falcon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
|
||||
udelay(10);
|
||||
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
|
||||
|
|
|
@ -38,6 +38,24 @@ nvfw_hs_header(struct nvkm_subdev *subdev, const void *data)
|
|||
return hdr;
|
||||
}
|
||||
|
||||
const struct nvfw_hs_header_v2 *
|
||||
nvfw_hs_header_v2(struct nvkm_subdev *subdev, const void *data)
|
||||
{
|
||||
const struct nvfw_hs_header_v2 *hdr = data;
|
||||
|
||||
nvkm_debug(subdev, "hsHeader:\n");
|
||||
nvkm_debug(subdev, "\tsigProdOffset : 0x%x\n", hdr->sig_prod_offset);
|
||||
nvkm_debug(subdev, "\tsigProdSize : 0x%x\n", hdr->sig_prod_size);
|
||||
nvkm_debug(subdev, "\tpatchLoc : 0x%x\n", hdr->patch_loc);
|
||||
nvkm_debug(subdev, "\tpatchSig : 0x%x\n", hdr->patch_sig);
|
||||
nvkm_debug(subdev, "\tmetadataOffset : 0x%x\n", hdr->meta_data_offset);
|
||||
nvkm_debug(subdev, "\tmetadataSize : 0x%x\n", hdr->meta_data_size);
|
||||
nvkm_debug(subdev, "\tnumSig : 0x%x\n", hdr->num_sig);
|
||||
nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset);
|
||||
nvkm_debug(subdev, "\theaderSize : 0x%x\n", hdr->header_size);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
const struct nvfw_hs_load_header *
|
||||
nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data)
|
||||
{
|
||||
|
@ -60,3 +78,24 @@ nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data)
|
|||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
const struct nvfw_hs_load_header_v2 *
|
||||
nvfw_hs_load_header_v2(struct nvkm_subdev *subdev, const void *data)
|
||||
{
|
||||
const struct nvfw_hs_load_header_v2 *hdr = data;
|
||||
int i;
|
||||
|
||||
nvkm_debug(subdev, "hsLoadHeader:\n");
|
||||
nvkm_debug(subdev, "\tosCodeOffset : 0x%x\n", hdr->os_code_offset);
|
||||
nvkm_debug(subdev, "\tosCodeSize : 0x%x\n", hdr->os_code_size);
|
||||
nvkm_debug(subdev, "\tosDataOffset : 0x%x\n", hdr->os_data_offset);
|
||||
nvkm_debug(subdev, "\tosDataSize : 0x%x\n", hdr->os_data_size);
|
||||
nvkm_debug(subdev, "\tnumApps : 0x%x\n", hdr->num_apps);
|
||||
for (i = 0; i < hdr->num_apps; i++) {
|
||||
nvkm_debug(subdev,
|
||||
"\tApp[%d] : offset 0x%x size 0x%x\n", i,
|
||||
hdr->app[i].offset, hdr->app[i].size);
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,30 @@
|
|||
#include "gf100.h"
|
||||
#include "ram.h"
|
||||
|
||||
#include <engine/nvdec.h>
|
||||
|
||||
static int
|
||||
ga102_fb_vpr_scrub(struct nvkm_fb *fb)
|
||||
{
|
||||
struct nvkm_falcon_fw fw = {};
|
||||
int ret;
|
||||
|
||||
ret = nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", &fb->subdev, "nvdec/scrubber",
|
||||
0, &fb->subdev.device->nvdec[0]->falcon, &fw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvkm_falcon_fw_boot(&fw, &fb->subdev, true, NULL, NULL, 0, 0);
|
||||
nvkm_falcon_fw_dtor(&fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
ga102_fb_vpr_scrub_required(struct nvkm_fb *fb)
|
||||
{
|
||||
return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0;
|
||||
}
|
||||
|
||||
static const struct nvkm_fb_func
|
||||
ga102_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
|
@ -32,6 +56,8 @@ ga102_fb = {
|
|||
.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
|
||||
.ram_new = ga102_ram_new,
|
||||
.default_bigpage = 16,
|
||||
.vpr.scrub_required = ga102_fb_vpr_scrub_required,
|
||||
.vpr.scrub = ga102_fb_vpr_scrub,
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -39,3 +65,9 @@ ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, s
|
|||
{
|
||||
return gp102_fb_new_(&ga102_fb, device, type, inst, pfb);
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga102/nvdec/scrubber.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/nvdec/scrubber.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/nvdec/scrubber.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/nvdec/scrubber.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/nvdec/scrubber.bin");
|
||||
|
|
Loading…
Reference in a new issue