drm/nouveau/acr/ga102: initial support
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
a51c69ee74
commit
4b569ded09
|
@ -39,6 +39,23 @@ struct wpr_header_v1 {
|
|||
|
||||
void wpr_header_v1_dump(struct nvkm_subdev *, const struct wpr_header_v1 *);
|
||||
|
||||
struct wpr_generic_header {
|
||||
#define WPR_GENERIC_HEADER_ID_LSF_UCODE_DESC 1
|
||||
#define WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER 2
|
||||
#define WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR 3
|
||||
#define WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER 4
|
||||
u16 identifier;
|
||||
u16 version;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct wpr_header_v2 {
|
||||
struct wpr_generic_header hdr;
|
||||
struct wpr_header_v1 wpr;
|
||||
};
|
||||
|
||||
void wpr_header_v2_dump(struct nvkm_subdev *, const struct wpr_header_v2 *);
|
||||
|
||||
struct lsf_signature {
|
||||
u8 prd_keys[2][16];
|
||||
u8 dbg_keys[2][16];
|
||||
|
@ -89,6 +106,74 @@ struct lsb_header_v1 {
|
|||
|
||||
void lsb_header_v1_dump(struct nvkm_subdev *, struct lsb_header_v1 *);
|
||||
|
||||
struct lsb_header_v2 {
|
||||
struct wpr_generic_header hdr;
|
||||
struct lsf_signature_v2 {
|
||||
struct wpr_generic_header hdr;
|
||||
u32 falcon_id;
|
||||
u8 prd_present;
|
||||
u8 dbg_present;
|
||||
u16 reserved;
|
||||
u32 sig_size;
|
||||
u8 prod_sig[2][384 + 128];
|
||||
u8 debug_sig[2][384 + 128];
|
||||
u16 sig_algo_ver;
|
||||
u16 sig_algo;
|
||||
u16 hash_algo_ver;
|
||||
u16 hash_algo;
|
||||
u32 sig_algo_padding_type;
|
||||
u8 depmap[11 * 2 * 4];
|
||||
u32 depmap_count;
|
||||
u8 supports_versioning;
|
||||
u8 pad[3];
|
||||
u32 ls_ucode_version;
|
||||
u32 ls_ucode_id;
|
||||
u32 ucode_ls_encrypted;
|
||||
u32 ls_eng_algo_type;
|
||||
u32 ls_eng_algo_ver;
|
||||
u8 ls_enc_iv[16];
|
||||
u8 rsvd[36];
|
||||
} signature;
|
||||
u32 ucode_off;
|
||||
u32 ucode_size;
|
||||
u32 data_size;
|
||||
u32 bl_code_size;
|
||||
u32 bl_imem_off;
|
||||
u32 bl_data_off;
|
||||
u32 bl_data_size;
|
||||
u32 rsvd0;
|
||||
u32 app_code_off;
|
||||
u32 app_code_size;
|
||||
u32 app_data_off;
|
||||
u32 app_data_size;
|
||||
u32 app_imem_offset;
|
||||
u32 app_dmem_offset;
|
||||
u32 flags;
|
||||
u32 monitor_code_offset;
|
||||
u32 monitor_data_offset;
|
||||
u32 manifest_offset;
|
||||
struct hs_fmc_params {
|
||||
u8 hs_fmc;
|
||||
u8 padding[3];
|
||||
u16 pkc_algo;
|
||||
u16 pkc_algo_version;
|
||||
u32 engid_mask;
|
||||
u32 ucode_id;
|
||||
u32 fuse_ver;
|
||||
u8 pkc_signature[384 + 128];
|
||||
u8 pkc_key[2048];
|
||||
u8 rsvd[4];
|
||||
} hs_fmc_params;
|
||||
struct hs_ovl_sig_blob_params {
|
||||
u8 hs_ovl_sig_blob_present;
|
||||
u32 hs_ovl_sig_blob_offset;
|
||||
u32 hs_ovl_sig_blob_size;
|
||||
} hs_ovl_sig_blob_params;
|
||||
u8 rsvd[20];
|
||||
};
|
||||
|
||||
void lsb_header_v2_dump(struct nvkm_subdev *, struct lsb_header_v2 *);
|
||||
|
||||
struct flcn_acr_desc {
|
||||
union {
|
||||
u8 reserved_dmem[0x200];
|
||||
|
|
|
@ -50,4 +50,55 @@ struct nvfw_ls_desc_v1 {
|
|||
|
||||
const struct nvfw_ls_desc_v1 *
|
||||
nvfw_ls_desc_v1(struct nvkm_subdev *, const void *);
|
||||
|
||||
struct nvfw_ls_desc_v2 {
|
||||
u32 descriptor_size;
|
||||
u32 image_size;
|
||||
u32 tools_version;
|
||||
u32 app_version;
|
||||
char date[64];
|
||||
u32 secure_bootloader;
|
||||
u32 bootloader_start_offset;
|
||||
u32 bootloader_size;
|
||||
u32 bootloader_imem_offset;
|
||||
u32 bootloader_entry_point;
|
||||
u32 app_start_offset;
|
||||
u32 app_size;
|
||||
u32 app_imem_offset;
|
||||
u32 app_imem_entry;
|
||||
u32 app_dmem_offset;
|
||||
u32 app_resident_code_offset;
|
||||
u32 app_resident_code_size;
|
||||
u32 app_resident_data_offset;
|
||||
u32 app_resident_data_size;
|
||||
u32 nb_imem_overlays;
|
||||
u32 nb_dmem_overlays;
|
||||
struct {
|
||||
u32 start;
|
||||
u32 size;
|
||||
} load_ovl[64];
|
||||
};
|
||||
|
||||
const struct nvfw_ls_desc_v2 *nvfw_ls_desc_v2(struct nvkm_subdev *, const void *);
|
||||
|
||||
struct nvfw_ls_hsbl_bin_hdr {
|
||||
u32 bin_magic;
|
||||
u32 bin_ver;
|
||||
u32 bin_size;
|
||||
u32 header_offset;
|
||||
};
|
||||
|
||||
const struct nvfw_ls_hsbl_bin_hdr *nvfw_ls_hsbl_bin_hdr(struct nvkm_subdev *, const void *);
|
||||
|
||||
struct nvfw_ls_hsbl_hdr {
|
||||
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;
|
||||
};
|
||||
|
||||
const struct nvfw_ls_hsbl_hdr *nvfw_ls_hsbl_hdr(struct nvkm_subdev *, const void *);
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,29 @@ struct nv_sec2_init_msg {
|
|||
u16 sw_managed_area_size;
|
||||
};
|
||||
|
||||
struct nv_sec2_init_msg_v1 {
|
||||
struct nvfw_falcon_msg hdr;
|
||||
#define NV_SEC2_INIT_MSG_INIT 0x00
|
||||
u8 msg_type;
|
||||
|
||||
u8 num_queues;
|
||||
u16 os_debug_entry_point;
|
||||
|
||||
struct {
|
||||
u32 offset;
|
||||
u16 size;
|
||||
u8 index;
|
||||
#define NV_SEC2_INIT_MSG_QUEUE_ID_CMDQ 0x00
|
||||
#define NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ 0x01
|
||||
u8 id;
|
||||
} queue_info[2];
|
||||
|
||||
u32 sw_managed_area_offset;
|
||||
u16 sw_managed_area_size;
|
||||
|
||||
u32 unkn[8];
|
||||
};
|
||||
|
||||
struct nv_sec2_acr_cmd {
|
||||
struct nvfw_falcon_cmd hdr;
|
||||
#define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00
|
||||
|
@ -62,4 +85,21 @@ struct nv_sec2_acr_bootstrap_falcon_msg {
|
|||
#define NV_SEC2_UNIT_V2_INIT 0x01
|
||||
#define NV_SEC2_UNIT_V2_UNLOAD 0x05
|
||||
#define NV_SEC2_UNIT_V2_ACR 0x07
|
||||
|
||||
struct nv_sec2_acr_bootstrap_falcon_cmd_v1 {
|
||||
struct nv_sec2_acr_cmd cmd;
|
||||
#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000
|
||||
#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001
|
||||
u32 flags;
|
||||
u32 falcon_id;
|
||||
u32 unkn08;
|
||||
u32 unkn0c;
|
||||
};
|
||||
|
||||
struct nv_sec2_acr_bootstrap_falcon_msg_v1 {
|
||||
struct nv_sec2_acr_msg msg;
|
||||
u32 error_code;
|
||||
u32 falcon_id;
|
||||
u32 unkn08;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -61,6 +61,7 @@ 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_select(struct nvkm_falcon *);
|
||||
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;
|
||||
|
|
|
@ -60,6 +60,7 @@ 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 *);
|
||||
int (*select)(struct nvkm_falcon *);
|
||||
u32 addr2;
|
||||
bool reset_pmc;
|
||||
int (*reset_eng)(struct nvkm_falcon *);
|
||||
|
|
|
@ -23,4 +23,5 @@ struct nvkm_sec2 {
|
|||
int gp102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
|
||||
int gp108_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
|
||||
int tu102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
|
||||
int ga102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
|
||||
#endif
|
||||
|
|
|
@ -67,6 +67,7 @@ int gp108_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
|
|||
int gp10b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
|
||||
int gv100_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
|
||||
int tu102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
|
||||
int ga102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
|
||||
|
||||
struct nvkm_acr_lsfw {
|
||||
const struct nvkm_acr_lsf_func *func;
|
||||
|
@ -79,6 +80,7 @@ struct nvkm_acr_lsfw {
|
|||
|
||||
const struct firmware *sig;
|
||||
|
||||
bool secure_bootloader;
|
||||
u32 bootloader_size;
|
||||
u32 bootloader_imem_offset;
|
||||
|
||||
|
@ -89,10 +91,19 @@ struct nvkm_acr_lsfw {
|
|||
u32 app_resident_code_size;
|
||||
u32 app_resident_data_offset;
|
||||
u32 app_resident_data_size;
|
||||
u32 app_imem_offset;
|
||||
u32 app_dmem_offset;
|
||||
|
||||
u32 ucode_size;
|
||||
u32 data_size;
|
||||
|
||||
u32 fuse_ver;
|
||||
u32 engine_id;
|
||||
u32 ucode_id;
|
||||
u32 sig_size;
|
||||
u32 sig_nr;
|
||||
u8 *sigs;
|
||||
|
||||
struct {
|
||||
u32 lsb;
|
||||
u32 img;
|
||||
|
@ -123,6 +134,12 @@ int
|
|||
nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *, struct nvkm_falcon *,
|
||||
enum nvkm_acr_lsf_id, const char *path,
|
||||
int ver, const struct nvkm_acr_lsf_func *);
|
||||
|
||||
int
|
||||
nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *, struct nvkm_falcon *,
|
||||
enum nvkm_acr_lsf_id, const char *path,
|
||||
int ver, const struct nvkm_acr_lsf_func *);
|
||||
|
||||
int
|
||||
nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *, struct nvkm_falcon *,
|
||||
enum nvkm_acr_lsf_id, const char *path,
|
||||
|
|
|
@ -12,4 +12,5 @@ struct nvkm_gsp {
|
|||
};
|
||||
|
||||
int gv100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
||||
int ga102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
||||
#endif
|
||||
|
|
|
@ -2596,12 +2596,14 @@ nv170_chipset = {
|
|||
static const struct nvkm_device_chip
|
||||
nv172_chipset = {
|
||||
.name = "GA102",
|
||||
.acr = { 0x00000001, ga102_acr_new },
|
||||
.bar = { 0x00000001, tu102_bar_new },
|
||||
.bios = { 0x00000001, nvkm_bios_new },
|
||||
.devinit = { 0x00000001, ga100_devinit_new },
|
||||
.fault = { 0x00000001, tu102_fault_new },
|
||||
.fb = { 0x00000001, ga102_fb_new },
|
||||
.gpio = { 0x00000001, ga102_gpio_new },
|
||||
.gsp = { 0x00000001, ga102_gsp_new },
|
||||
.i2c = { 0x00000001, gm200_i2c_new },
|
||||
.imem = { 0x00000001, nv50_instmem_new },
|
||||
.mc = { 0x00000001, ga100_mc_new },
|
||||
|
@ -2616,17 +2618,20 @@ nv172_chipset = {
|
|||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
.sec2 = { 0x00000001, ga102_sec2_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
nv173_chipset = {
|
||||
.name = "GA103",
|
||||
.acr = { 0x00000001, ga102_acr_new },
|
||||
.bar = { 0x00000001, tu102_bar_new },
|
||||
.bios = { 0x00000001, nvkm_bios_new },
|
||||
.devinit = { 0x00000001, ga100_devinit_new },
|
||||
.fault = { 0x00000001, tu102_fault_new },
|
||||
.fb = { 0x00000001, ga102_fb_new },
|
||||
.gpio = { 0x00000001, ga102_gpio_new },
|
||||
.gsp = { 0x00000001, ga102_gsp_new },
|
||||
.i2c = { 0x00000001, gm200_i2c_new },
|
||||
.imem = { 0x00000001, nv50_instmem_new },
|
||||
.mc = { 0x00000001, ga100_mc_new },
|
||||
|
@ -2641,17 +2646,20 @@ nv173_chipset = {
|
|||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
.sec2 = { 0x00000001, ga102_sec2_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
nv174_chipset = {
|
||||
.name = "GA104",
|
||||
.acr = { 0x00000001, ga102_acr_new },
|
||||
.bar = { 0x00000001, tu102_bar_new },
|
||||
.bios = { 0x00000001, nvkm_bios_new },
|
||||
.devinit = { 0x00000001, ga100_devinit_new },
|
||||
.fault = { 0x00000001, tu102_fault_new },
|
||||
.fb = { 0x00000001, ga102_fb_new },
|
||||
.gpio = { 0x00000001, ga102_gpio_new },
|
||||
.gsp = { 0x00000001, ga102_gsp_new },
|
||||
.i2c = { 0x00000001, gm200_i2c_new },
|
||||
.imem = { 0x00000001, nv50_instmem_new },
|
||||
.mc = { 0x00000001, ga100_mc_new },
|
||||
|
@ -2666,17 +2674,20 @@ nv174_chipset = {
|
|||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
.sec2 = { 0x00000001, ga102_sec2_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
nv176_chipset = {
|
||||
.name = "GA106",
|
||||
.acr = { 0x00000001, ga102_acr_new },
|
||||
.bar = { 0x00000001, tu102_bar_new },
|
||||
.bios = { 0x00000001, nvkm_bios_new },
|
||||
.devinit = { 0x00000001, ga100_devinit_new },
|
||||
.fault = { 0x00000001, tu102_fault_new },
|
||||
.fb = { 0x00000001, ga102_fb_new },
|
||||
.gpio = { 0x00000001, ga102_gpio_new },
|
||||
.gsp = { 0x00000001, ga102_gsp_new },
|
||||
.i2c = { 0x00000001, gm200_i2c_new },
|
||||
.imem = { 0x00000001, nv50_instmem_new },
|
||||
.mc = { 0x00000001, ga100_mc_new },
|
||||
|
@ -2691,17 +2702,20 @@ nv176_chipset = {
|
|||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
.sec2 = { 0x00000001, ga102_sec2_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
nv177_chipset = {
|
||||
.name = "GA107",
|
||||
.acr = { 0x00000001, ga102_acr_new },
|
||||
.bar = { 0x00000001, tu102_bar_new },
|
||||
.bios = { 0x00000001, nvkm_bios_new },
|
||||
.devinit = { 0x00000001, ga100_devinit_new },
|
||||
.fault = { 0x00000001, tu102_fault_new },
|
||||
.fb = { 0x00000001, ga102_fb_new },
|
||||
.gpio = { 0x00000001, ga102_gpio_new },
|
||||
.gsp = { 0x00000001, ga102_gsp_new },
|
||||
.i2c = { 0x00000001, gm200_i2c_new },
|
||||
.imem = { 0x00000001, nv50_instmem_new },
|
||||
.mc = { 0x00000001, ga100_mc_new },
|
||||
|
@ -2716,6 +2730,7 @@ nv177_chipset = {
|
|||
.dma = { 0x00000001, gv100_dma_new },
|
||||
.fifo = { 0x00000001, ga102_fifo_new },
|
||||
.nvdec = { 0x00000001, ga102_nvdec_new },
|
||||
.sec2 = { 0x00000001, ga102_sec2_new },
|
||||
};
|
||||
|
||||
struct nvkm_subdev *
|
||||
|
|
|
@ -3,3 +3,4 @@ nvkm-y += nvkm/engine/sec2/base.o
|
|||
nvkm-y += nvkm/engine/sec2/gp102.o
|
||||
nvkm-y += nvkm/engine/sec2/gp108.o
|
||||
nvkm-y += nvkm/engine/sec2/tu102.o
|
||||
nvkm-y += nvkm/engine/sec2/ga102.o
|
||||
|
|
|
@ -100,6 +100,12 @@ nvkm_sec2_oneinit(struct nvkm_engine *engine)
|
|||
struct nvkm_intr *intr = &sec2->engine.subdev.device->mc->intr;
|
||||
enum nvkm_intr_type type = NVKM_INTR_SUBDEV;
|
||||
|
||||
if (sec2->func->intr_vector) {
|
||||
intr = sec2->func->intr_vector(sec2, &type);
|
||||
if (IS_ERR(intr))
|
||||
return PTR_ERR(intr);
|
||||
}
|
||||
|
||||
return nvkm_inth_add(intr, type, NVKM_INTR_PRIO_NORMAL, subdev, sec2->func->intr,
|
||||
&subdev->inth);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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/acr.h>
|
||||
#include <subdev/vfn.h>
|
||||
|
||||
#include <nvfw/flcn.h>
|
||||
#include <nvfw/sec2.h>
|
||||
|
||||
static int
|
||||
ga102_sec2_initmsg(struct nvkm_sec2 *sec2)
|
||||
{
|
||||
struct nv_sec2_init_msg_v1 msg;
|
||||
int ret, i;
|
||||
|
||||
ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT ||
|
||||
msg.msg_type != NV_SEC2_INIT_MSG_INIT)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) {
|
||||
if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) {
|
||||
nvkm_falcon_msgq_init(sec2->msgq, msg.queue_info[i].index,
|
||||
msg.queue_info[i].offset,
|
||||
msg.queue_info[i].size);
|
||||
} else {
|
||||
nvkm_falcon_cmdq_init(sec2->cmdq, msg.queue_info[i].index,
|
||||
msg.queue_info[i].offset,
|
||||
msg.queue_info[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nvkm_intr *
|
||||
ga102_sec2_intr_vector(struct nvkm_sec2 *sec2, enum nvkm_intr_type *pvector)
|
||||
{
|
||||
struct nvkm_device *device = sec2->engine.subdev.device;
|
||||
struct nvkm_falcon *falcon = &sec2->falcon;
|
||||
int ret;
|
||||
|
||||
ret = ga102_flcn_select(falcon);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
*pvector = nvkm_rd32(device, 0x8403e0) & 0x000000ff;
|
||||
return &device->vfn->intr;
|
||||
}
|
||||
|
||||
static int
|
||||
ga102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr)
|
||||
{
|
||||
struct nv_sec2_acr_bootstrap_falcon_msg_v1 *msg =
|
||||
container_of(hdr, typeof(*msg), msg.hdr);
|
||||
struct nvkm_subdev *subdev = priv;
|
||||
const char *name = nvkm_acr_lsf_id(msg->falcon_id);
|
||||
|
||||
if (msg->error_code) {
|
||||
nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for falcon %d [%s]: %08x %08x\n",
|
||||
msg->falcon_id, name, msg->error_code, msg->unkn08);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nvkm_debug(subdev, "%s booted\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ga102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon);
|
||||
struct nv_sec2_acr_bootstrap_falcon_cmd_v1 cmd = {
|
||||
.cmd.hdr.unit_id = sec2->func->unit_acr,
|
||||
.cmd.hdr.size = sizeof(cmd),
|
||||
.cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON,
|
||||
.flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
|
||||
.falcon_id = id,
|
||||
};
|
||||
|
||||
return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr,
|
||||
ga102_sec2_acr_bootstrap_falcon_callback,
|
||||
&sec2->engine.subdev,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static const struct nvkm_acr_lsf_func
|
||||
ga102_sec2_acr_0 = {
|
||||
.bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
|
||||
.bld_write = gp102_sec2_acr_bld_write_1,
|
||||
.bld_patch = gp102_sec2_acr_bld_patch_1,
|
||||
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
|
||||
BIT_ULL(NVKM_ACR_LSF_GPCCS) |
|
||||
BIT_ULL(NVKM_ACR_LSF_SEC2),
|
||||
.bootstrap_falcon = ga102_sec2_acr_bootstrap_falcon,
|
||||
};
|
||||
|
||||
static const struct nvkm_falcon_func
|
||||
ga102_sec2_flcn = {
|
||||
.disable = gm200_flcn_disable,
|
||||
.enable = gm200_flcn_enable,
|
||||
.select = ga102_flcn_select,
|
||||
.addr2 = 0x1000,
|
||||
.reset_pmc = true,
|
||||
.reset_eng = gp102_flcn_reset_eng,
|
||||
.reset_prep = ga102_flcn_reset_prep,
|
||||
.reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing,
|
||||
.imem_dma = &ga102_flcn_dma,
|
||||
.dmem_pio = &gm200_flcn_dmem_pio,
|
||||
.dmem_dma = &ga102_flcn_dma,
|
||||
.emem_addr = 0x01000000,
|
||||
.emem_pio = &gp102_flcn_emem_pio,
|
||||
.start = nvkm_falcon_v1_start,
|
||||
.cmdq = { 0xc00, 0xc04, 8 },
|
||||
.msgq = { 0xc80, 0xc84, 8 },
|
||||
};
|
||||
|
||||
static const struct nvkm_sec2_func
|
||||
ga102_sec2 = {
|
||||
.flcn = &ga102_sec2_flcn,
|
||||
.intr_vector = ga102_sec2_intr_vector,
|
||||
.intr = gp102_sec2_intr,
|
||||
.initmsg = ga102_sec2_initmsg,
|
||||
.unit_acr = NV_SEC2_UNIT_V2_ACR,
|
||||
.unit_unload = NV_SEC2_UNIT_V2_UNLOAD,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga102/sec2/desc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga102/sec2/image.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga102/sec2/sig.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga102/sec2/hs_bl_sig.bin");
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga103/sec2/desc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/sec2/image.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/sec2/sig.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/sec2/hs_bl_sig.bin");
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga104/sec2/desc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/sec2/image.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/sec2/sig.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/sec2/hs_bl_sig.bin");
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga106/sec2/desc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/sec2/image.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/sec2/sig.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/sec2/hs_bl_sig.bin");
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga107/sec2/desc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/sec2/image.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/sec2/sig.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/sec2/hs_bl_sig.bin");
|
||||
|
||||
static int
|
||||
ga102_sec2_load(struct nvkm_sec2 *sec2, int ver,
|
||||
const struct nvkm_sec2_fwif *fwif)
|
||||
{
|
||||
return nvkm_acr_lsfw_load_sig_image_desc_v2(&sec2->engine.subdev, &sec2->falcon,
|
||||
NVKM_ACR_LSF_SEC2, "sec2/", ver, fwif->acr);
|
||||
}
|
||||
|
||||
static const struct nvkm_sec2_fwif
|
||||
ga102_sec2_fwif[] = {
|
||||
{ 0, ga102_sec2_load, &ga102_sec2, &ga102_sec2_acr_0 },
|
||||
{ -1, gp102_sec2_nofw, &ga102_sec2 }
|
||||
};
|
||||
|
||||
int
|
||||
ga102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_sec2 **psec2)
|
||||
{
|
||||
/* TOP info wasn't updated on Turing to reflect the PRI
|
||||
* address change for some reason. We override it here.
|
||||
*/
|
||||
return nvkm_sec2_new_(ga102_sec2_fwif, device, type, inst, 0x840000, psec2);
|
||||
}
|
|
@ -237,7 +237,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
|
|||
MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
|
||||
MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
|
||||
|
||||
static void
|
||||
void
|
||||
gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust)
|
||||
{
|
||||
struct flcn_bl_dmem_desc_v2 hdr;
|
||||
|
@ -248,7 +248,7 @@ gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust)
|
|||
flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld,
|
||||
struct nvkm_acr_lsfw *lsfw)
|
||||
{
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
#ifndef __NVKM_SEC2_PRIV_H__
|
||||
#define __NVKM_SEC2_PRIV_H__
|
||||
#include <engine/sec2.h>
|
||||
struct nvkm_acr_lsfw;
|
||||
|
||||
struct nvkm_sec2_func {
|
||||
const struct nvkm_falcon_func *flcn;
|
||||
u8 unit_unload;
|
||||
u8 unit_acr;
|
||||
struct nvkm_intr *(*intr_vector)(struct nvkm_sec2 *, enum nvkm_intr_type *);
|
||||
irqreturn_t (*intr)(struct nvkm_inth *);
|
||||
int (*initmsg)(struct nvkm_sec2 *);
|
||||
};
|
||||
|
@ -25,6 +27,8 @@ int gp102_sec2_nofw(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *);
|
|||
int gp102_sec2_load(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *);
|
||||
extern const struct nvkm_sec2_func gp102_sec2;
|
||||
extern const struct nvkm_acr_lsf_func gp102_sec2_acr_1;
|
||||
void gp102_sec2_acr_bld_write_1(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
|
||||
void gp102_sec2_acr_bld_patch_1(struct nvkm_acr *, u32, s64);
|
||||
|
||||
int nvkm_sec2_new_(const struct nvkm_sec2_fwif *, struct nvkm_device *, enum nvkm_subdev_type,
|
||||
int, u32 addr, struct nvkm_sec2 **);
|
||||
|
|
|
@ -77,14 +77,28 @@ ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
|
|||
int
|
||||
ga102_flcn_reset_prep(struct nvkm_falcon *falcon)
|
||||
{
|
||||
const u32 addr2 = (falcon->owner->type != NVKM_ENGINE_NVDEC) ? 0x530 : 0x930;
|
||||
nvkm_falcon_rd32(falcon, 0x0f4);
|
||||
|
||||
if (nvkm_msec(falcon->owner->device, 10,
|
||||
if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x1ec) & 0x00000003) == 0x00000001 &&
|
||||
(nvkm_falcon_rd32(falcon, addr2) & 0x00000008) == 0x00000008)
|
||||
nvkm_usec(falcon->owner->device, 150,
|
||||
if (nvkm_falcon_rd32(falcon, 0x0f4) & 0x80000000)
|
||||
break;
|
||||
) < 0)
|
||||
return -ETIMEDOUT;
|
||||
_warn = false;
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ga102_flcn_select(struct nvkm_falcon *falcon)
|
||||
{
|
||||
if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x668) & 0x00000010) != 0x00000000) {
|
||||
nvkm_falcon_wr32(falcon, falcon->addr2 + 0x668, 0x00000000);
|
||||
if (nvkm_msec(falcon->owner->device, 10,
|
||||
if (nvkm_falcon_rd32(falcon, falcon->addr2 + 0x668) & 0x00000001)
|
||||
break;
|
||||
) < 0)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,12 @@ gm200_flcn_enable(struct nvkm_falcon *falcon)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (falcon->func->select) {
|
||||
ret = falcon->func->select(falcon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (falcon->func->reset_pmc)
|
||||
nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst);
|
||||
|
||||
|
@ -168,6 +174,12 @@ gm200_flcn_disable(struct nvkm_falcon *falcon)
|
|||
struct nvkm_device *device = falcon->owner->device;
|
||||
int ret;
|
||||
|
||||
if (falcon->func->select) {
|
||||
ret = falcon->func->select(falcon);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000);
|
||||
nvkm_falcon_wr32(falcon, 0x014, 0xffffffff);
|
||||
|
||||
|
|
|
@ -45,6 +45,47 @@ wpr_header_v1_dump(struct nvkm_subdev *subdev, const struct wpr_header_v1 *hdr)
|
|||
nvkm_debug(subdev, "\tstatus : %d\n", hdr->status);
|
||||
}
|
||||
|
||||
void
|
||||
wpr_generic_header_dump(struct nvkm_subdev *subdev, const struct wpr_generic_header *hdr)
|
||||
{
|
||||
nvkm_debug(subdev, "wprGenericHeader\n");
|
||||
nvkm_debug(subdev, "\tidentifier : %04x\n", hdr->identifier);
|
||||
nvkm_debug(subdev, "\tversion : %04x\n", hdr->version);
|
||||
nvkm_debug(subdev, "\tsize : %08x\n", hdr->size);
|
||||
}
|
||||
|
||||
void
|
||||
wpr_header_v2_dump(struct nvkm_subdev *subdev, const struct wpr_header_v2 *hdr)
|
||||
{
|
||||
wpr_generic_header_dump(subdev, &hdr->hdr);
|
||||
wpr_header_v1_dump(subdev, &hdr->wpr);
|
||||
}
|
||||
|
||||
void
|
||||
lsb_header_v2_dump(struct nvkm_subdev *subdev, struct lsb_header_v2 *hdr)
|
||||
{
|
||||
wpr_generic_header_dump(subdev, &hdr->hdr);
|
||||
nvkm_debug(subdev, "lsbHeader\n");
|
||||
nvkm_debug(subdev, "\tucodeOff : 0x%x\n", hdr->ucode_off);
|
||||
nvkm_debug(subdev, "\tucodeSize : 0x%x\n", hdr->ucode_size);
|
||||
nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size);
|
||||
nvkm_debug(subdev, "\tblCodeSize : 0x%x\n", hdr->bl_code_size);
|
||||
nvkm_debug(subdev, "\tblImemOff : 0x%x\n", hdr->bl_imem_off);
|
||||
nvkm_debug(subdev, "\tblDataOff : 0x%x\n", hdr->bl_data_off);
|
||||
nvkm_debug(subdev, "\tblDataSize : 0x%x\n", hdr->bl_data_size);
|
||||
nvkm_debug(subdev, "\treserved0 : %08x\n", hdr->rsvd0);
|
||||
nvkm_debug(subdev, "\tappCodeOff : 0x%x\n", hdr->app_code_off);
|
||||
nvkm_debug(subdev, "\tappCodeSize : 0x%x\n", hdr->app_code_size);
|
||||
nvkm_debug(subdev, "\tappDataOff : 0x%x\n", hdr->app_data_off);
|
||||
nvkm_debug(subdev, "\tappDataSize : 0x%x\n", hdr->app_data_size);
|
||||
nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", hdr->app_imem_offset);
|
||||
nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", hdr->app_dmem_offset);
|
||||
nvkm_debug(subdev, "\tflags : 0x%x\n", hdr->flags);
|
||||
nvkm_debug(subdev, "\tmonitorCodeOff: 0x%x\n", hdr->monitor_code_offset);
|
||||
nvkm_debug(subdev, "\tmonitorDataOff: 0x%x\n", hdr->monitor_data_offset);
|
||||
nvkm_debug(subdev, "\tmanifestOffset: 0x%x\n", hdr->manifest_offset);
|
||||
}
|
||||
|
||||
static void
|
||||
lsb_header_tail_dump(struct nvkm_subdev *subdev, struct lsb_header_tail *hdr)
|
||||
{
|
||||
|
|
|
@ -106,3 +106,75 @@ nvfw_ls_desc_v1(struct nvkm_subdev *subdev, const void *data)
|
|||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
const struct nvfw_ls_desc_v2 *
|
||||
nvfw_ls_desc_v2(struct nvkm_subdev *subdev, const void *data)
|
||||
{
|
||||
const struct nvfw_ls_desc_v2 *hdr = data;
|
||||
char *date;
|
||||
int i;
|
||||
|
||||
nvkm_debug(subdev, "lsUcodeImgDesc:\n");
|
||||
nvkm_debug(subdev, "\tdescriptorSize : %d\n", hdr->descriptor_size);
|
||||
nvkm_debug(subdev, "\timageSize : %d\n", hdr->image_size);
|
||||
nvkm_debug(subdev, "\ttoolsVersion : 0x%x\n", hdr->tools_version);
|
||||
nvkm_debug(subdev, "\tappVersion : 0x%x\n", hdr->app_version);
|
||||
|
||||
date = kstrndup(hdr->date, sizeof(hdr->date), GFP_KERNEL);
|
||||
nvkm_debug(subdev, "\tdate : %s\n", date);
|
||||
kfree(date);
|
||||
|
||||
nvkm_debug(subdev, "\tsecureBootloader : 0x%x\n", hdr->secure_bootloader);
|
||||
nvkm_debug(subdev, "\tbootloaderStartOffset: 0x%x\n", hdr->bootloader_start_offset);
|
||||
nvkm_debug(subdev, "\tbootloaderSize : 0x%x\n", hdr->bootloader_size);
|
||||
nvkm_debug(subdev, "\tbootloaderImemOffset : 0x%x\n", hdr->bootloader_imem_offset);
|
||||
nvkm_debug(subdev, "\tbootloaderEntryPoint : 0x%x\n", hdr->bootloader_entry_point);
|
||||
|
||||
nvkm_debug(subdev, "\tappStartOffset : 0x%x\n", hdr->app_start_offset);
|
||||
nvkm_debug(subdev, "\tappSize : 0x%x\n", hdr->app_size);
|
||||
nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", hdr->app_imem_offset);
|
||||
nvkm_debug(subdev, "\tappImemEntry : 0x%x\n", hdr->app_imem_entry);
|
||||
nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", hdr->app_dmem_offset);
|
||||
nvkm_debug(subdev, "\tappResidentCodeOffset: 0x%x\n", hdr->app_resident_code_offset);
|
||||
nvkm_debug(subdev, "\tappResidentCodeSize : 0x%x\n", hdr->app_resident_code_size);
|
||||
nvkm_debug(subdev, "\tappResidentDataOffset: 0x%x\n", hdr->app_resident_data_offset);
|
||||
nvkm_debug(subdev, "\tappResidentDataSize : 0x%x\n", hdr->app_resident_data_size);
|
||||
|
||||
nvkm_debug(subdev, "\tnbImemOverlays : %d\n", hdr->nb_imem_overlays);
|
||||
nvkm_debug(subdev, "\tnbDmemOverlays : %d\n", hdr->nb_dmem_overlays);
|
||||
for (i = 0; i < ARRAY_SIZE(hdr->load_ovl); i++) {
|
||||
nvkm_debug(subdev, "\tloadOvl[%d] : 0x%x %d\n", i,
|
||||
hdr->load_ovl[i].start, hdr->load_ovl[i].size);
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
const struct nvfw_ls_hsbl_bin_hdr *
|
||||
nvfw_ls_hsbl_bin_hdr(struct nvkm_subdev *subdev, const void *data)
|
||||
{
|
||||
const struct nvfw_ls_hsbl_bin_hdr *hdr = data;
|
||||
|
||||
nvkm_debug(subdev, "lsHsblBinHdr:\n");
|
||||
nvkm_debug(subdev, "\tbinMagic : 0x%08x\n", hdr->bin_magic);
|
||||
nvkm_debug(subdev, "\tbinVer : %d\n", hdr->bin_ver);
|
||||
nvkm_debug(subdev, "\tbinSize : %d\n", hdr->bin_size);
|
||||
nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
const struct nvfw_ls_hsbl_hdr *
|
||||
nvfw_ls_hsbl_hdr(struct nvkm_subdev *subdev, const void *data)
|
||||
{
|
||||
const struct nvfw_ls_hsbl_hdr *hdr = data;
|
||||
|
||||
nvkm_debug(subdev, "lsHsblHdr:\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);
|
||||
return hdr;
|
||||
}
|
||||
|
|
|
@ -8,3 +8,5 @@ nvkm-y += nvkm/subdev/acr/gp108.o
|
|||
nvkm-y += nvkm/subdev/acr/gv100.o
|
||||
nvkm-y += nvkm/subdev/acr/gp10b.o
|
||||
nvkm-y += nvkm/subdev/acr/tu102.o
|
||||
nvkm-y += nvkm/subdev/acr/ga100.o
|
||||
nvkm-y += nvkm/subdev/acr/ga102.o
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
void
|
||||
ga100_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit)
|
||||
{
|
||||
struct nvkm_device *device = acr->subdev.device;
|
||||
|
||||
*start = (u64)(nvkm_rd32(device, 0x1fa81c) & 0xffffff00) << 8;
|
||||
*limit = (u64)(nvkm_rd32(device, 0x1fa820) & 0xffffff00) << 8;
|
||||
*limit = *limit + 0x20000;
|
||||
}
|
||||
|
||||
int
|
||||
ga100_acr_hsfw_ctor(struct nvkm_acr *acr, const char *bl, const char *fw,
|
||||
const char *name, int ver, const struct nvkm_acr_hsf_fwif *fwif)
|
||||
{
|
||||
struct nvkm_acr_hsfw *hsfw;
|
||||
|
||||
if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
|
||||
hsfw->falcon_id = fwif->falcon_id;
|
||||
hsfw->boot_mbox0 = fwif->boot_mbox0;
|
||||
hsfw->intr_clear = fwif->intr_clear;
|
||||
list_add_tail(&hsfw->head, &acr->hsfw);
|
||||
|
||||
return nvkm_falcon_fw_ctor_hs_v2(fwif->func, name, &acr->subdev, fw, ver, NULL, &hsfw->fw);
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* 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 <nvfw/acr.h>
|
||||
|
||||
static int
|
||||
ga102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
|
||||
{
|
||||
struct wpr_header_v2 hdr;
|
||||
struct lsb_header_v2 *lsb;
|
||||
struct nvkm_acr_lsfw *lsfw;
|
||||
u32 offset = 0;
|
||||
|
||||
lsb = kvmalloc(sizeof(*lsb), GFP_KERNEL);
|
||||
if (!lsb)
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
nvkm_robj(acr->wpr, offset, &hdr, sizeof(hdr));
|
||||
wpr_header_v2_dump(&acr->subdev, &hdr);
|
||||
|
||||
list_for_each_entry(lsfw, &acr->lsfw, head) {
|
||||
if (lsfw->id != hdr.wpr.falcon_id)
|
||||
continue;
|
||||
|
||||
nvkm_robj(acr->wpr, hdr.wpr.lsb_offset, lsb, sizeof(*lsb));
|
||||
lsb_header_v2_dump(&acr->subdev, lsb);
|
||||
|
||||
lsfw->func->bld_patch(acr, lsb->bl_data_off, adjust);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(hdr);
|
||||
} while (hdr.wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID);
|
||||
|
||||
kvfree(lsb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ga102_acr_wpr_build_lsb(struct nvkm_acr *acr, struct nvkm_acr_lsfw *lsfw)
|
||||
{
|
||||
struct lsb_header_v2 *hdr;
|
||||
int ret = 0;
|
||||
|
||||
if (WARN_ON(lsfw->sig->size != sizeof(hdr->signature)))
|
||||
return -EINVAL;
|
||||
|
||||
hdr = kvzalloc(sizeof(*hdr), GFP_KERNEL);
|
||||
if (!hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr->hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER;
|
||||
hdr->hdr.version = 2;
|
||||
hdr->hdr.size = sizeof(*hdr);
|
||||
|
||||
memcpy(&hdr->signature, lsfw->sig->data, lsfw->sig->size);
|
||||
hdr->ucode_off = lsfw->offset.img;
|
||||
hdr->ucode_size = lsfw->ucode_size;
|
||||
hdr->data_size = lsfw->data_size;
|
||||
hdr->bl_code_size = lsfw->bootloader_size;
|
||||
hdr->bl_imem_off = lsfw->bootloader_imem_offset;
|
||||
hdr->bl_data_off = lsfw->offset.bld;
|
||||
hdr->bl_data_size = lsfw->bl_data_size;
|
||||
hdr->app_code_off = lsfw->app_start_offset + lsfw->app_resident_code_offset;
|
||||
hdr->app_code_size = ALIGN(lsfw->app_resident_code_size, 0x100);
|
||||
hdr->app_data_off = lsfw->app_start_offset + lsfw->app_resident_data_offset;
|
||||
hdr->app_data_size = ALIGN(lsfw->app_resident_data_size, 0x100);
|
||||
hdr->app_imem_offset = lsfw->app_imem_offset;
|
||||
hdr->app_dmem_offset = lsfw->app_dmem_offset;
|
||||
hdr->flags = lsfw->func->flags;
|
||||
hdr->monitor_code_offset = 0;
|
||||
hdr->monitor_data_offset = 0;
|
||||
hdr->manifest_offset = 0;
|
||||
|
||||
if (lsfw->secure_bootloader) {
|
||||
struct nvkm_falcon_fw fw = {
|
||||
.fw.img = hdr->hs_fmc_params.pkc_signature,
|
||||
.fw.name = "LSFW",
|
||||
.func = &(const struct nvkm_falcon_fw_func) {
|
||||
.signature = ga100_flcn_fw_signature,
|
||||
},
|
||||
.sig_size = lsfw->sig_size,
|
||||
.sig_nr = lsfw->sig_nr,
|
||||
.sigs = lsfw->sigs,
|
||||
.fuse_ver = lsfw->fuse_ver,
|
||||
.engine_id = lsfw->engine_id,
|
||||
.ucode_id = lsfw->ucode_id,
|
||||
.falcon = lsfw->falcon,
|
||||
|
||||
};
|
||||
|
||||
ret = nvkm_falcon_get(fw.falcon, &acr->subdev);
|
||||
if (ret == 0) {
|
||||
hdr->hs_fmc_params.hs_fmc = 1;
|
||||
hdr->hs_fmc_params.pkc_algo = 0;
|
||||
hdr->hs_fmc_params.pkc_algo_version = 1;
|
||||
hdr->hs_fmc_params.engid_mask = lsfw->engine_id;
|
||||
hdr->hs_fmc_params.ucode_id = lsfw->ucode_id;
|
||||
hdr->hs_fmc_params.fuse_ver = lsfw->fuse_ver;
|
||||
ret = nvkm_falcon_fw_patch(&fw);
|
||||
nvkm_falcon_put(fw.falcon, &acr->subdev);
|
||||
}
|
||||
}
|
||||
|
||||
nvkm_wobj(acr->wpr, lsfw->offset.lsb, hdr, sizeof(*hdr));
|
||||
kvfree(hdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ga102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos)
|
||||
{
|
||||
struct nvkm_acr_lsfw *lsfw;
|
||||
struct wpr_header_v2 hdr;
|
||||
u32 offset = 0;
|
||||
int ret;
|
||||
|
||||
/*XXX: shared sub-WPR headers, fill terminator for now. */
|
||||
nvkm_wo32(acr->wpr, 0x300, (2 << 16) | WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR);
|
||||
nvkm_wo32(acr->wpr, 0x304, 0x14);
|
||||
nvkm_wo32(acr->wpr, 0x308, 0xffffffff);
|
||||
nvkm_wo32(acr->wpr, 0x30c, 0);
|
||||
nvkm_wo32(acr->wpr, 0x310, 0);
|
||||
|
||||
/* Fill per-LSF structures. */
|
||||
list_for_each_entry(lsfw, &acr->lsfw, head) {
|
||||
struct lsf_signature_v2 *sig = (void *)lsfw->sig->data;
|
||||
|
||||
hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER;
|
||||
hdr.hdr.version = 2;
|
||||
hdr.hdr.size = sizeof(hdr);
|
||||
hdr.wpr.falcon_id = lsfw->id;
|
||||
hdr.wpr.lsb_offset = lsfw->offset.lsb;
|
||||
hdr.wpr.bootstrap_owner = NVKM_ACR_LSF_GSPLITE;
|
||||
hdr.wpr.lazy_bootstrap = 1;
|
||||
hdr.wpr.bin_version = sig->ls_ucode_version;
|
||||
hdr.wpr.status = WPR_HEADER_V1_STATUS_COPY;
|
||||
|
||||
/* Write WPR header. */
|
||||
nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
|
||||
offset += sizeof(hdr);
|
||||
|
||||
/* Write LSB header. */
|
||||
ret = ga102_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. */
|
||||
hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER;
|
||||
hdr.hdr.version = 2;
|
||||
hdr.hdr.size = sizeof(hdr);
|
||||
hdr.wpr.falcon_id = WPR_HEADER_V1_FALCON_ID_INVALID;
|
||||
nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32
|
||||
ga102_acr_wpr_layout(struct nvkm_acr *acr)
|
||||
{
|
||||
struct nvkm_acr_lsfw *lsfw;
|
||||
u32 wpr = 0;
|
||||
|
||||
wpr += 21 /* MAX_LSF */ * sizeof(struct wpr_header_v2);
|
||||
wpr = ALIGN(wpr, 256);
|
||||
|
||||
wpr += 0x100; /* Shared sub-WPR headers. */
|
||||
|
||||
list_for_each_entry(lsfw, &acr->lsfw, head) {
|
||||
wpr = ALIGN(wpr, 256);
|
||||
lsfw->offset.lsb = wpr;
|
||||
wpr += sizeof(struct lsb_header_v2);
|
||||
|
||||
wpr = ALIGN(wpr, 4096);
|
||||
lsfw->offset.img = wpr;
|
||||
wpr += lsfw->img.size;
|
||||
|
||||
wpr = ALIGN(wpr, 256);
|
||||
lsfw->offset.bld = wpr;
|
||||
lsfw->bl_data_size = ALIGN(lsfw->func->bld_size, 256);
|
||||
wpr += lsfw->bl_data_size;
|
||||
}
|
||||
|
||||
return wpr;
|
||||
}
|
||||
|
||||
static int
|
||||
ga102_acr_wpr_parse(struct nvkm_acr *acr)
|
||||
{
|
||||
const struct wpr_header_v2 *hdr = (void *)acr->wpr_fw->data;
|
||||
|
||||
while (hdr->wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) {
|
||||
wpr_header_v2_dump(&acr->subdev, hdr);
|
||||
if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->wpr.falcon_id))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga102/acr/ucode_unload.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/acr/ucode_unload.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/acr/ucode_unload.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/acr/ucode_unload.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/acr/ucode_unload.bin");
|
||||
|
||||
static const struct nvkm_acr_hsf_fwif
|
||||
ga102_acr_unload_fwif[] = {
|
||||
{ 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_SEC2 },
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga102/acr/ucode_asb.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/acr/ucode_asb.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/acr/ucode_asb.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/acr/ucode_asb.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/acr/ucode_asb.bin");
|
||||
|
||||
static const struct nvkm_acr_hsf_fwif
|
||||
ga102_acr_asb_fwif[] = {
|
||||
{ 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_GSP },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct nvkm_falcon_fw_func
|
||||
ga102_acr_ahesasc_0 = {
|
||||
.signature = ga100_flcn_fw_signature,
|
||||
.reset = gm200_flcn_fw_reset,
|
||||
.setup = gp102_acr_load_setup,
|
||||
.load = ga102_flcn_fw_load,
|
||||
.boot = ga102_flcn_fw_boot,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE("nvidia/ga102/acr/ucode_ahesasc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga103/acr/ucode_ahesasc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga104/acr/ucode_ahesasc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga106/acr/ucode_ahesasc.bin");
|
||||
MODULE_FIRMWARE("nvidia/ga107/acr/ucode_ahesasc.bin");
|
||||
|
||||
static const struct nvkm_acr_hsf_fwif
|
||||
ga102_acr_ahesasc_fwif[] = {
|
||||
{ 0, ga100_acr_hsfw_ctor, &ga102_acr_ahesasc_0, NVKM_ACR_HSF_SEC2 },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct nvkm_acr_func
|
||||
ga102_acr = {
|
||||
.ahesasc = ga102_acr_ahesasc_fwif,
|
||||
.asb = ga102_acr_asb_fwif,
|
||||
.unload = ga102_acr_unload_fwif,
|
||||
.wpr_parse = ga102_acr_wpr_parse,
|
||||
.wpr_layout = ga102_acr_wpr_layout,
|
||||
.wpr_alloc = gp102_acr_wpr_alloc,
|
||||
.wpr_patch = ga102_acr_wpr_patch,
|
||||
.wpr_build = ga102_acr_wpr_build,
|
||||
.wpr_check = ga100_acr_wpr_check,
|
||||
.init = tu102_acr_init,
|
||||
};
|
||||
|
||||
static int
|
||||
ga102_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, NULL, "acr/ucode_ahesasc", "AHESASC");
|
||||
if (IS_ERR(hsfwif))
|
||||
return PTR_ERR(hsfwif);
|
||||
|
||||
hsfwif = nvkm_firmware_load(subdev, fwif->func->asb, "AcrASB",
|
||||
acr, NULL, "acr/ucode_asb", "ASB");
|
||||
if (IS_ERR(hsfwif))
|
||||
return PTR_ERR(hsfwif);
|
||||
|
||||
hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload",
|
||||
acr, NULL, "acr/ucode_unload", "unload");
|
||||
if (IS_ERR(hsfwif))
|
||||
return PTR_ERR(hsfwif);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nvkm_acr_fwif
|
||||
ga102_acr_fwif[] = {
|
||||
{ 0, ga102_acr_load, &ga102_acr },
|
||||
{ -1, gm200_acr_nofw, &gm200_acr },
|
||||
{}
|
||||
};
|
||||
|
||||
int
|
||||
ga102_acr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_acr **pacr)
|
||||
{
|
||||
return nvkm_acr_new_(ga102_acr_fwif, device, type, inst, pacr);
|
||||
}
|
|
@ -61,7 +61,7 @@ gm200_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit)
|
|||
*limit = *limit + 0x20000;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &acr->subdev;
|
||||
|
@ -86,6 +86,8 @@ gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
|
|||
}
|
||||
offset += sizeof(hdr);
|
||||
} while (hdr.falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <nvfw/acr.h>
|
||||
#include <nvfw/flcn.h>
|
||||
|
||||
void
|
||||
int
|
||||
gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
|
||||
{
|
||||
struct wpr_header_v1 hdr;
|
||||
|
@ -54,6 +54,8 @@ gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
|
|||
|
||||
offset += sizeof(hdr);
|
||||
} while (hdr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -29,6 +29,7 @@ void
|
|||
nvkm_acr_lsfw_del(struct nvkm_acr_lsfw *lsfw)
|
||||
{
|
||||
nvkm_blob_dtor(&lsfw->img);
|
||||
kfree(lsfw->sigs);
|
||||
nvkm_firmware_put(lsfw->sig);
|
||||
list_del(&lsfw->head);
|
||||
kfree(lsfw);
|
||||
|
@ -176,6 +177,75 @@ nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *subdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev,
|
||||
struct nvkm_falcon *falcon,
|
||||
enum nvkm_acr_lsf_id id,
|
||||
const char *path, int ver,
|
||||
const struct nvkm_acr_lsf_func *func)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
struct nvkm_acr_lsfw *lsfw;
|
||||
const struct nvfw_ls_desc_v2 *desc;
|
||||
int ret = 0;
|
||||
|
||||
lsfw = nvkm_acr_lsfw_load_sig_image_desc_(subdev, falcon, id, path, ver, func, &fw);
|
||||
if (IS_ERR(lsfw))
|
||||
return PTR_ERR(lsfw);
|
||||
|
||||
desc = nvfw_ls_desc_v2(subdev, fw->data);
|
||||
|
||||
lsfw->secure_bootloader = desc->secure_bootloader;
|
||||
lsfw->bootloader_size = ALIGN(desc->bootloader_size, 256);
|
||||
lsfw->bootloader_imem_offset = desc->bootloader_imem_offset;
|
||||
|
||||
lsfw->app_size = ALIGN(desc->app_size, 256);
|
||||
lsfw->app_start_offset = desc->app_start_offset;
|
||||
lsfw->app_imem_entry = desc->app_imem_entry;
|
||||
lsfw->app_resident_code_offset = desc->app_resident_code_offset;
|
||||
lsfw->app_resident_code_size = desc->app_resident_code_size;
|
||||
lsfw->app_resident_data_offset = desc->app_resident_data_offset;
|
||||
lsfw->app_resident_data_size = desc->app_resident_data_size;
|
||||
lsfw->app_imem_offset = desc->app_imem_offset;
|
||||
lsfw->app_dmem_offset = desc->app_dmem_offset;
|
||||
|
||||
lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + lsfw->bootloader_size;
|
||||
lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - lsfw->ucode_size;
|
||||
|
||||
nvkm_firmware_put(fw);
|
||||
|
||||
if (lsfw->secure_bootloader) {
|
||||
const struct firmware *hsbl;
|
||||
const struct nvfw_ls_hsbl_bin_hdr *hdr;
|
||||
const struct nvfw_ls_hsbl_hdr *hshdr;
|
||||
u32 loc, sig, cnt, *meta;
|
||||
|
||||
ret = nvkm_firmware_load_name(subdev, path, "hs_bl_sig", ver, &hsbl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdr = nvfw_ls_hsbl_bin_hdr(subdev, hsbl->data);
|
||||
hshdr = nvfw_ls_hsbl_hdr(subdev, hsbl->data + hdr->header_offset);
|
||||
meta = (u32 *)(hsbl->data + hshdr->meta_data_offset);
|
||||
loc = *(u32 *)(hsbl->data + hshdr->patch_loc);
|
||||
sig = *(u32 *)(hsbl->data + hshdr->patch_sig);
|
||||
cnt = *(u32 *)(hsbl->data + hshdr->num_sig);
|
||||
|
||||
lsfw->fuse_ver = meta[0];
|
||||
lsfw->engine_id = meta[1];
|
||||
lsfw->ucode_id = meta[2];
|
||||
lsfw->sig_size = hshdr->sig_prod_size / cnt;
|
||||
lsfw->sig_nr = cnt;
|
||||
lsfw->sigs = kmemdup(hsbl->data + hshdr->sig_prod_offset + sig,
|
||||
lsfw->sig_nr * lsfw->sig_size, GFP_KERNEL);
|
||||
nvkm_firmware_put(hsbl);
|
||||
if (!lsfw->sigs)
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *subdev,
|
||||
struct nvkm_falcon *falcon,
|
||||
|
|
|
@ -24,7 +24,7 @@ struct nvkm_acr_func {
|
|||
u32 (*wpr_layout)(struct nvkm_acr *);
|
||||
int (*wpr_alloc)(struct nvkm_acr *, u32 wpr_size);
|
||||
int (*wpr_build)(struct nvkm_acr *, struct nvkm_acr_lsf *rtos);
|
||||
void (*wpr_patch)(struct nvkm_acr *, s64 adjust);
|
||||
int (*wpr_patch)(struct nvkm_acr *, s64 adjust);
|
||||
void (*wpr_check)(struct nvkm_acr *, u64 *start, u64 *limit);
|
||||
int (*init)(struct nvkm_acr *);
|
||||
void (*fini)(struct nvkm_acr *);
|
||||
|
@ -35,7 +35,7 @@ extern const struct nvkm_acr_func gm200_acr;
|
|||
int gm200_acr_wpr_parse(struct nvkm_acr *);
|
||||
u32 gm200_acr_wpr_layout(struct nvkm_acr *);
|
||||
int gm200_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *);
|
||||
void gm200_acr_wpr_patch(struct nvkm_acr *, s64);
|
||||
int gm200_acr_wpr_patch(struct nvkm_acr *, s64);
|
||||
void gm200_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *);
|
||||
void gm200_acr_wpr_build_lsb_tail(struct nvkm_acr_lsfw *,
|
||||
struct lsb_header_tail *);
|
||||
|
@ -48,7 +48,11 @@ u32 gp102_acr_wpr_layout(struct nvkm_acr *);
|
|||
int gp102_acr_wpr_alloc(struct nvkm_acr *, u32 wpr_size);
|
||||
int gp102_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *);
|
||||
int gp102_acr_wpr_build_lsb(struct nvkm_acr *, struct nvkm_acr_lsfw *);
|
||||
void gp102_acr_wpr_patch(struct nvkm_acr *, s64);
|
||||
int gp102_acr_wpr_patch(struct nvkm_acr *, s64);
|
||||
|
||||
int tu102_acr_init(struct nvkm_acr *);
|
||||
|
||||
void ga100_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *);
|
||||
|
||||
struct nvkm_acr_hsfw {
|
||||
struct nvkm_falcon_fw fw;
|
||||
|
@ -93,6 +97,9 @@ extern const struct nvkm_falcon_fw_func gp108_acr_load_0;
|
|||
extern const struct nvkm_falcon_fw_func gp108_acr_hsfw_0;
|
||||
int gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *);
|
||||
|
||||
int ga100_acr_hsfw_ctor(struct nvkm_acr *, const char *, const char *, const char *, int,
|
||||
const struct nvkm_acr_hsf_fwif *);
|
||||
|
||||
int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, enum nvkm_subdev_type,
|
||||
int inst, struct nvkm_acr **);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include <nvfw/acr.h>
|
||||
|
||||
static int
|
||||
int
|
||||
tu102_acr_init(struct nvkm_acr *acr)
|
||||
{
|
||||
int ret = nvkm_acr_hsfw_boot(acr, "AHESASC");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
nvkm-y += nvkm/subdev/gsp/base.o
|
||||
nvkm-y += nvkm/subdev/gsp/gv100.o
|
||||
nvkm-y += nvkm/subdev/gsp/ga102.o
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
static const struct nvkm_falcon_func
|
||||
ga102_gsp_flcn = {
|
||||
.disable = gm200_flcn_disable,
|
||||
.enable = gm200_flcn_enable,
|
||||
.select = ga102_flcn_select,
|
||||
.addr2 = 0x1000,
|
||||
.reset_eng = gp102_flcn_reset_eng,
|
||||
.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_gsp_func
|
||||
ga102_gsp = {
|
||||
.flcn = &ga102_gsp_flcn,
|
||||
};
|
||||
|
||||
static int
|
||||
ga102_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nvkm_gsp_fwif
|
||||
ga102_gsps[] = {
|
||||
{ -1, ga102_gsp_nofw, &ga102_gsp },
|
||||
{}
|
||||
};
|
||||
|
||||
int
|
||||
ga102_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_gsp **pgsp)
|
||||
{
|
||||
return nvkm_gsp_new_(ga102_gsps, device, type, inst, pgsp);
|
||||
}
|
Loading…
Reference in New Issue