Commit a51c69ee authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fb/ga102: load and boot VPR scrubber FW

v2. fixup for ga103 early merge
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarGourav Samaiya <gsamaiya@nvidia.com>
parent 21876b0e
...@@ -17,6 +17,20 @@ struct nvfw_hs_header { ...@@ -17,6 +17,20 @@ struct nvfw_hs_header {
const struct nvfw_hs_header *nvfw_hs_header(struct nvkm_subdev *, const void *); 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 { struct nvfw_hs_load_header {
u32 non_sec_code_off; u32 non_sec_code_off;
u32 non_sec_code_size; u32 non_sec_code_size;
...@@ -28,4 +42,18 @@ struct nvfw_hs_load_header { ...@@ -28,4 +42,18 @@ struct nvfw_hs_load_header {
const struct nvfw_hs_load_header * const struct nvfw_hs_load_header *
nvfw_hs_load_header(struct nvkm_subdev *, const void *); 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 #endif
...@@ -31,6 +31,13 @@ struct nvkm_falcon_func_pio { ...@@ -31,6 +31,13 @@ struct nvkm_falcon_func_pio {
void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len); 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, int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner,
const char *name, u32 addr, struct nvkm_falcon *); const char *name, u32 addr, struct nvkm_falcon *);
void nvkm_falcon_dtor(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 ...@@ -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); 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, 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); 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_reset_wait_mem_scrubbing(struct nvkm_falcon *);
int gm200_flcn_disable(struct nvkm_falcon *); int gm200_flcn_disable(struct nvkm_falcon *);
...@@ -52,6 +61,10 @@ void gm200_flcn_tracepc(struct nvkm_falcon *); ...@@ -52,6 +61,10 @@ void gm200_flcn_tracepc(struct nvkm_falcon *);
int gp102_flcn_reset_eng(struct nvkm_falcon *); int gp102_flcn_reset_eng(struct nvkm_falcon *);
extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio; 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 nvkm_falcon_v1_load_imem(struct nvkm_falcon *,
void *, u32, u32, u16, u8, bool); void *, u32, u32, u16, u8, bool);
void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
...@@ -87,6 +100,9 @@ struct nvkm_falcon_fw { ...@@ -87,6 +100,9 @@ struct nvkm_falcon_fw {
u32 sig_size; u32 sig_size;
int sig_nr; int sig_nr;
u8 *sigs; u8 *sigs;
u32 fuse_ver;
u32 engine_id;
u32 ucode_id;
u32 nmem_base_img; u32 nmem_base_img;
u32 nmem_base; u32 nmem_base;
...@@ -117,6 +133,9 @@ int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, st ...@@ -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, 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_subdev *, const char *bl, const char *img, int ver,
struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw); 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 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 sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg);
int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *); int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *);
...@@ -132,6 +151,12 @@ int gm200_flcn_fw_reset(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_load(struct nvkm_falcon_fw *);
int gm200_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32); 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_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_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) #define FLCNFW_ERR(f,fmt,a...) FLCNFW_PRINTK((f), ERROR, err, fmt"\n", ##a)
......
...@@ -19,6 +19,7 @@ struct nvkm_falcon { ...@@ -19,6 +19,7 @@ struct nvkm_falcon {
struct nvkm_subdev *owner; struct nvkm_subdev *owner;
const char *name; const char *name;
u32 addr; u32 addr;
u32 addr2;
struct mutex mutex; struct mutex mutex;
struct mutex dmem_mutex; struct mutex dmem_mutex;
...@@ -59,8 +60,10 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *, ...@@ -59,8 +60,10 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *,
struct nvkm_falcon_func { struct nvkm_falcon_func {
int (*disable)(struct nvkm_falcon *); int (*disable)(struct nvkm_falcon *);
int (*enable)(struct nvkm_falcon *); int (*enable)(struct nvkm_falcon *);
u32 addr2;
bool reset_pmc; bool reset_pmc;
int (*reset_eng)(struct nvkm_falcon *); int (*reset_eng)(struct nvkm_falcon *);
int (*reset_prep)(struct nvkm_falcon *);
int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *); int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *);
u32 debug; u32 debug;
...@@ -69,7 +72,10 @@ struct nvkm_falcon_func { ...@@ -69,7 +72,10 @@ struct nvkm_falcon_func {
bool bind_intr; bool bind_intr;
const struct nvkm_falcon_func_pio *imem_pio; 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_pio *dmem_pio;
const struct nvkm_falcon_func_dma *dmem_dma;
u32 emem_addr; u32 emem_addr;
const struct nvkm_falcon_func_pio *emem_pio; const struct nvkm_falcon_func_pio *emem_pio;
......
...@@ -12,4 +12,5 @@ struct nvkm_nvdec { ...@@ -12,4 +12,5 @@ struct nvkm_nvdec {
}; };
int gm107_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, 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 #endif
...@@ -2615,6 +2615,7 @@ nv172_chipset = { ...@@ -2615,6 +2615,7 @@ nv172_chipset = {
.disp = { 0x00000001, ga102_disp_new }, .disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new }, .dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new }, .fifo = { 0x00000001, ga102_fifo_new },
.nvdec = { 0x00000001, ga102_nvdec_new },
}; };
static const struct nvkm_device_chip static const struct nvkm_device_chip
...@@ -2639,6 +2640,7 @@ nv173_chipset = { ...@@ -2639,6 +2640,7 @@ nv173_chipset = {
.disp = { 0x00000001, ga102_disp_new }, .disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new }, .dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new }, .fifo = { 0x00000001, ga102_fifo_new },
.nvdec = { 0x00000001, ga102_nvdec_new },
}; };
static const struct nvkm_device_chip static const struct nvkm_device_chip
...@@ -2663,6 +2665,7 @@ nv174_chipset = { ...@@ -2663,6 +2665,7 @@ nv174_chipset = {
.disp = { 0x00000001, ga102_disp_new }, .disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new }, .dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new }, .fifo = { 0x00000001, ga102_fifo_new },
.nvdec = { 0x00000001, ga102_nvdec_new },
}; };
static const struct nvkm_device_chip static const struct nvkm_device_chip
...@@ -2687,6 +2690,7 @@ nv176_chipset = { ...@@ -2687,6 +2690,7 @@ nv176_chipset = {
.disp = { 0x00000001, ga102_disp_new }, .disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new }, .dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new }, .fifo = { 0x00000001, ga102_fifo_new },
.nvdec = { 0x00000001, ga102_nvdec_new },
}; };
static const struct nvkm_device_chip static const struct nvkm_device_chip
...@@ -2711,6 +2715,7 @@ nv177_chipset = { ...@@ -2711,6 +2715,7 @@ nv177_chipset = {
.disp = { 0x00000001, ga102_disp_new }, .disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new }, .dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new }, .fifo = { 0x00000001, ga102_fifo_new },
.nvdec = { 0x00000001, ga102_nvdec_new },
}; };
struct nvkm_subdev * struct nvkm_subdev *
......
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
nvkm-y += nvkm/engine/nvdec/base.o nvkm-y += nvkm/engine/nvdec/base.o
nvkm-y += nvkm/engine/nvdec/gm107.o nvkm-y += nvkm/engine/nvdec/gm107.o
nvkm-y += nvkm/engine/nvdec/ga102.o
...@@ -37,7 +37,7 @@ nvkm_nvdec = { ...@@ -37,7 +37,7 @@ nvkm_nvdec = {
int int
nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device, 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; struct nvkm_nvdec *nvdec;
int ret; int ret;
...@@ -57,5 +57,5 @@ nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device, ...@@ -57,5 +57,5 @@ nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device,
nvdec->func = fwif->func; nvdec->func = fwif->func;
return nvkm_falcon_ctor(nvdec->func->flcn, &nvdec->engine.subdev, return nvkm_falcon_ctor(nvdec->func->flcn, &nvdec->engine.subdev,
nvdec->engine.subdev.name, 0, &nvdec->falcon); nvdec->engine.subdev.name, addr, &nvdec->falcon);
}; };
/*
* 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 ...@@ -54,5 +54,5 @@ int
gm107_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, gm107_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_nvdec **pnvdec) 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 { ...@@ -15,5 +15,5 @@ struct nvkm_nvdec_fwif {
}; };
int nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *, 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 #endif
...@@ -8,3 +8,5 @@ nvkm-y += nvkm/falcon/v1.o ...@@ -8,3 +8,5 @@ nvkm-y += nvkm/falcon/v1.o
nvkm-y += nvkm/falcon/gm200.o nvkm-y += nvkm/falcon/gm200.o
nvkm-y += nvkm/falcon/gp102.o nvkm-y += nvkm/falcon/gp102.o
nvkm-y += nvkm/falcon/ga100.o
nvkm-y += nvkm/falcon/ga102.o
...@@ -25,6 +25,82 @@ ...@@ -25,6 +25,82 @@
#include <subdev/timer.h> #include <subdev/timer.h>
#include <subdev/top.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 * static const struct nvkm_falcon_func_pio *
nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base) 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, ...@@ -239,6 +315,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
falcon->owner = subdev; falcon->owner = subdev;
falcon->name = name; falcon->name = name;
falcon->addr = addr; falcon->addr = addr;
falcon->addr2 = func->addr2;
mutex_init(&falcon->mutex); mutex_init(&falcon->mutex);
mutex_init(&falcon->dmem_mutex); mutex_init(&falcon->dmem_mutex);
return 0; return 0;
......
...@@ -294,3 +294,61 @@ nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name, ...@@ -294,3 +294,61 @@ nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name,
nvkm_firmware_put(blob); nvkm_firmware_put(blob);
return ret; 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;
}
/*
* 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;
}
/*
* 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) ...@@ -171,8 +171,15 @@ gm200_flcn_disable(struct nvkm_falcon *falcon)
nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000); nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000);
nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); 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); nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
}
if (falcon->func->reset_eng) { if (falcon->func->reset_eng) {
ret = falcon->func->reset_eng(falcon); ret = falcon->func->reset_eng(falcon);
......
...@@ -66,6 +66,14 @@ gp102_flcn_emem_pio = { ...@@ -66,6 +66,14 @@ gp102_flcn_emem_pio = {
int int
gp102_flcn_reset_eng(struct nvkm_falcon *falcon) 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); nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
udelay(10); udelay(10);
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000); nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
......
...@@ -38,6 +38,24 @@ nvfw_hs_header(struct nvkm_subdev *subdev, const void *data) ...@@ -38,6 +38,24 @@ nvfw_hs_header(struct nvkm_subdev *subdev, const void *data)
return hdr; 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 * const struct nvfw_hs_load_header *
nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data) 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) ...@@ -60,3 +78,24 @@ nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data)
return hdr; 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 @@ ...@@ -22,6 +22,30 @@
#include "gf100.h" #include "gf100.h"
#include "ram.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 static const struct nvkm_fb_func
ga102_fb = { ga102_fb = {
.dtor = gf100_fb_dtor, .dtor = gf100_fb_dtor,
...@@ -32,6 +56,8 @@ ga102_fb = { ...@@ -32,6 +56,8 @@ ga102_fb = {
.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init, .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.ram_new = ga102_ram_new, .ram_new = ga102_ram_new,
.default_bigpage = 16, .default_bigpage = 16,
.vpr.scrub_required = ga102_fb_vpr_scrub_required,
.vpr.scrub = ga102_fb_vpr_scrub,
}; };
int int
...@@ -39,3 +65,9 @@ ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, s ...@@ -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); 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");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment